souleyez 2.43.29__py3-none-any.whl → 2.43.34__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 (358) hide show
  1. souleyez/__init__.py +1 -2
  2. souleyez/ai/__init__.py +21 -15
  3. souleyez/ai/action_mapper.py +249 -150
  4. souleyez/ai/chain_advisor.py +116 -100
  5. souleyez/ai/claude_provider.py +29 -28
  6. souleyez/ai/context_builder.py +80 -62
  7. souleyez/ai/executor.py +158 -117
  8. souleyez/ai/feedback_handler.py +136 -121
  9. souleyez/ai/llm_factory.py +27 -20
  10. souleyez/ai/llm_provider.py +4 -2
  11. souleyez/ai/ollama_provider.py +6 -9
  12. souleyez/ai/ollama_service.py +44 -37
  13. souleyez/ai/path_scorer.py +91 -76
  14. souleyez/ai/recommender.py +176 -144
  15. souleyez/ai/report_context.py +74 -73
  16. souleyez/ai/report_service.py +84 -66
  17. souleyez/ai/result_parser.py +222 -229
  18. souleyez/ai/safety.py +67 -44
  19. souleyez/auth/__init__.py +23 -22
  20. souleyez/auth/audit.py +36 -26
  21. souleyez/auth/engagement_access.py +65 -48
  22. souleyez/auth/permissions.py +14 -3
  23. souleyez/auth/session_manager.py +54 -37
  24. souleyez/auth/user_manager.py +109 -64
  25. souleyez/commands/audit.py +40 -43
  26. souleyez/commands/auth.py +35 -15
  27. souleyez/commands/deliverables.py +55 -50
  28. souleyez/commands/engagement.py +47 -28
  29. souleyez/commands/license.py +32 -23
  30. souleyez/commands/screenshots.py +36 -32
  31. souleyez/commands/user.py +82 -36
  32. souleyez/config.py +52 -44
  33. souleyez/core/credential_tester.py +87 -81
  34. souleyez/core/cve_mappings.py +179 -192
  35. souleyez/core/cve_matcher.py +162 -148
  36. souleyez/core/msf_auto_mapper.py +100 -83
  37. souleyez/core/msf_chain_engine.py +294 -256
  38. souleyez/core/msf_database.py +153 -70
  39. souleyez/core/msf_integration.py +679 -673
  40. souleyez/core/msf_rpc_client.py +40 -42
  41. souleyez/core/msf_rpc_manager.py +77 -79
  42. souleyez/core/msf_sync_manager.py +241 -181
  43. souleyez/core/network_utils.py +22 -15
  44. souleyez/core/parser_handler.py +34 -25
  45. souleyez/core/pending_chains.py +114 -63
  46. souleyez/core/templates.py +158 -107
  47. souleyez/core/tool_chaining.py +9526 -2879
  48. souleyez/core/version_utils.py +79 -94
  49. souleyez/core/vuln_correlation.py +136 -89
  50. souleyez/core/web_utils.py +33 -32
  51. souleyez/data/wordlists/ad_users.txt +378 -0
  52. souleyez/data/wordlists/api_endpoints_large.txt +769 -0
  53. souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
  54. souleyez/data/wordlists/lfi_payloads.txt +82 -0
  55. souleyez/data/wordlists/passwords_brute.txt +1548 -0
  56. souleyez/data/wordlists/passwords_crack.txt +2479 -0
  57. souleyez/data/wordlists/passwords_spray.txt +386 -0
  58. souleyez/data/wordlists/subdomains_large.txt +5057 -0
  59. souleyez/data/wordlists/usernames_common.txt +694 -0
  60. souleyez/data/wordlists/web_dirs_large.txt +4769 -0
  61. souleyez/detection/__init__.py +1 -1
  62. souleyez/detection/attack_signatures.py +12 -17
  63. souleyez/detection/mitre_mappings.py +61 -55
  64. souleyez/detection/validator.py +97 -86
  65. souleyez/devtools.py +23 -10
  66. souleyez/docs/README.md +4 -4
  67. souleyez/docs/api-reference/cli-commands.md +2 -2
  68. souleyez/docs/developer-guide/adding-new-tools.md +562 -0
  69. souleyez/docs/user-guide/auto-chaining.md +30 -8
  70. souleyez/docs/user-guide/getting-started.md +1 -1
  71. souleyez/docs/user-guide/installation.md +26 -3
  72. souleyez/docs/user-guide/metasploit-integration.md +2 -2
  73. souleyez/docs/user-guide/rbac.md +1 -1
  74. souleyez/docs/user-guide/scope-management.md +1 -1
  75. souleyez/docs/user-guide/siem-integration.md +1 -1
  76. souleyez/docs/user-guide/tools-reference.md +1 -8
  77. souleyez/docs/user-guide/worker-management.md +1 -1
  78. souleyez/engine/background.py +1239 -535
  79. souleyez/engine/base.py +4 -1
  80. souleyez/engine/job_status.py +17 -49
  81. souleyez/engine/log_sanitizer.py +103 -77
  82. souleyez/engine/manager.py +38 -7
  83. souleyez/engine/result_handler.py +2200 -1550
  84. souleyez/engine/worker_manager.py +50 -41
  85. souleyez/export/evidence_bundle.py +72 -62
  86. souleyez/feature_flags/features.py +16 -20
  87. souleyez/feature_flags.py +5 -9
  88. souleyez/handlers/__init__.py +11 -0
  89. souleyez/handlers/base.py +188 -0
  90. souleyez/handlers/bash_handler.py +277 -0
  91. souleyez/handlers/bloodhound_handler.py +243 -0
  92. souleyez/handlers/certipy_handler.py +311 -0
  93. souleyez/handlers/crackmapexec_handler.py +486 -0
  94. souleyez/handlers/dnsrecon_handler.py +344 -0
  95. souleyez/handlers/enum4linux_handler.py +400 -0
  96. souleyez/handlers/evil_winrm_handler.py +493 -0
  97. souleyez/handlers/ffuf_handler.py +815 -0
  98. souleyez/handlers/gobuster_handler.py +1114 -0
  99. souleyez/handlers/gpp_extract_handler.py +334 -0
  100. souleyez/handlers/hashcat_handler.py +444 -0
  101. souleyez/handlers/hydra_handler.py +563 -0
  102. souleyez/handlers/impacket_getuserspns_handler.py +343 -0
  103. souleyez/handlers/impacket_psexec_handler.py +222 -0
  104. souleyez/handlers/impacket_secretsdump_handler.py +426 -0
  105. souleyez/handlers/john_handler.py +286 -0
  106. souleyez/handlers/katana_handler.py +425 -0
  107. souleyez/handlers/kerbrute_handler.py +298 -0
  108. souleyez/handlers/ldapsearch_handler.py +636 -0
  109. souleyez/handlers/lfi_extract_handler.py +464 -0
  110. souleyez/handlers/msf_auxiliary_handler.py +408 -0
  111. souleyez/handlers/msf_exploit_handler.py +380 -0
  112. souleyez/handlers/nikto_handler.py +413 -0
  113. souleyez/handlers/nmap_handler.py +821 -0
  114. souleyez/handlers/nuclei_handler.py +359 -0
  115. souleyez/handlers/nxc_handler.py +371 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +292 -0
  118. souleyez/handlers/responder_handler.py +232 -0
  119. souleyez/handlers/service_explorer_handler.py +434 -0
  120. souleyez/handlers/smbclient_handler.py +344 -0
  121. souleyez/handlers/smbmap_handler.py +510 -0
  122. souleyez/handlers/smbpasswd_handler.py +296 -0
  123. souleyez/handlers/sqlmap_handler.py +1116 -0
  124. souleyez/handlers/theharvester_handler.py +601 -0
  125. souleyez/handlers/web_login_test_handler.py +327 -0
  126. souleyez/handlers/whois_handler.py +277 -0
  127. souleyez/handlers/wpscan_handler.py +554 -0
  128. souleyez/history.py +32 -16
  129. souleyez/importers/msf_importer.py +106 -75
  130. souleyez/importers/smart_importer.py +208 -147
  131. souleyez/integrations/siem/__init__.py +10 -10
  132. souleyez/integrations/siem/base.py +17 -18
  133. souleyez/integrations/siem/elastic.py +108 -122
  134. souleyez/integrations/siem/factory.py +207 -80
  135. souleyez/integrations/siem/googlesecops.py +146 -154
  136. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  137. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  138. souleyez/integrations/siem/sentinel.py +107 -109
  139. souleyez/integrations/siem/splunk.py +246 -212
  140. souleyez/integrations/siem/wazuh.py +65 -71
  141. souleyez/integrations/wazuh/__init__.py +5 -5
  142. souleyez/integrations/wazuh/client.py +70 -93
  143. souleyez/integrations/wazuh/config.py +85 -57
  144. souleyez/integrations/wazuh/host_mapper.py +28 -36
  145. souleyez/integrations/wazuh/sync.py +78 -68
  146. souleyez/intelligence/__init__.py +4 -5
  147. souleyez/intelligence/correlation_analyzer.py +309 -295
  148. souleyez/intelligence/exploit_knowledge.py +661 -623
  149. souleyez/intelligence/exploit_suggestions.py +159 -139
  150. souleyez/intelligence/gap_analyzer.py +132 -97
  151. souleyez/intelligence/gap_detector.py +251 -214
  152. souleyez/intelligence/sensitive_tables.py +266 -129
  153. souleyez/intelligence/service_parser.py +137 -123
  154. souleyez/intelligence/surface_analyzer.py +407 -268
  155. souleyez/intelligence/target_parser.py +159 -162
  156. souleyez/licensing/__init__.py +6 -6
  157. souleyez/licensing/validator.py +17 -19
  158. souleyez/log_config.py +79 -54
  159. souleyez/main.py +1505 -687
  160. souleyez/migrations/fix_job_counter.py +16 -14
  161. souleyez/parsers/bloodhound_parser.py +41 -39
  162. souleyez/parsers/crackmapexec_parser.py +178 -111
  163. souleyez/parsers/dalfox_parser.py +72 -77
  164. souleyez/parsers/dnsrecon_parser.py +103 -91
  165. souleyez/parsers/enum4linux_parser.py +183 -153
  166. souleyez/parsers/ffuf_parser.py +29 -25
  167. souleyez/parsers/gobuster_parser.py +301 -41
  168. souleyez/parsers/hashcat_parser.py +324 -79
  169. souleyez/parsers/http_fingerprint_parser.py +350 -103
  170. souleyez/parsers/hydra_parser.py +131 -111
  171. souleyez/parsers/impacket_parser.py +231 -178
  172. souleyez/parsers/john_parser.py +98 -86
  173. souleyez/parsers/katana_parser.py +316 -0
  174. souleyez/parsers/msf_parser.py +943 -498
  175. souleyez/parsers/nikto_parser.py +346 -65
  176. souleyez/parsers/nmap_parser.py +262 -174
  177. souleyez/parsers/nuclei_parser.py +40 -44
  178. souleyez/parsers/responder_parser.py +26 -26
  179. souleyez/parsers/searchsploit_parser.py +74 -74
  180. souleyez/parsers/service_explorer_parser.py +279 -0
  181. souleyez/parsers/smbmap_parser.py +180 -124
  182. souleyez/parsers/sqlmap_parser.py +434 -308
  183. souleyez/parsers/theharvester_parser.py +75 -57
  184. souleyez/parsers/whois_parser.py +135 -94
  185. souleyez/parsers/wpscan_parser.py +278 -190
  186. souleyez/plugins/afp.py +44 -36
  187. souleyez/plugins/afp_brute.py +114 -46
  188. souleyez/plugins/ard.py +48 -37
  189. souleyez/plugins/bloodhound.py +95 -61
  190. souleyez/plugins/certipy.py +303 -0
  191. souleyez/plugins/crackmapexec.py +186 -85
  192. souleyez/plugins/dalfox.py +120 -59
  193. souleyez/plugins/dns_hijack.py +146 -41
  194. souleyez/plugins/dnsrecon.py +97 -61
  195. souleyez/plugins/enum4linux.py +91 -66
  196. souleyez/plugins/evil_winrm.py +291 -0
  197. souleyez/plugins/ffuf.py +166 -90
  198. souleyez/plugins/firmware_extract.py +133 -29
  199. souleyez/plugins/gobuster.py +387 -190
  200. souleyez/plugins/gpp_extract.py +393 -0
  201. souleyez/plugins/hashcat.py +100 -73
  202. souleyez/plugins/http_fingerprint.py +854 -267
  203. souleyez/plugins/hydra.py +566 -200
  204. souleyez/plugins/impacket_getnpusers.py +117 -69
  205. souleyez/plugins/impacket_psexec.py +84 -64
  206. souleyez/plugins/impacket_secretsdump.py +103 -69
  207. souleyez/plugins/impacket_smbclient.py +89 -75
  208. souleyez/plugins/john.py +86 -69
  209. souleyez/plugins/katana.py +313 -0
  210. souleyez/plugins/kerbrute.py +237 -0
  211. souleyez/plugins/lfi_extract.py +541 -0
  212. souleyez/plugins/macos_ssh.py +117 -48
  213. souleyez/plugins/mdns.py +35 -30
  214. souleyez/plugins/msf_auxiliary.py +253 -130
  215. souleyez/plugins/msf_exploit.py +239 -161
  216. souleyez/plugins/nikto.py +134 -78
  217. souleyez/plugins/nmap.py +275 -91
  218. souleyez/plugins/nuclei.py +180 -89
  219. souleyez/plugins/nxc.py +285 -0
  220. souleyez/plugins/plugin_base.py +35 -36
  221. souleyez/plugins/plugin_template.py +13 -5
  222. souleyez/plugins/rdp_sec_check.py +130 -0
  223. souleyez/plugins/responder.py +112 -71
  224. souleyez/plugins/router_http_brute.py +76 -65
  225. souleyez/plugins/router_ssh_brute.py +118 -41
  226. souleyez/plugins/router_telnet_brute.py +124 -42
  227. souleyez/plugins/routersploit.py +91 -59
  228. souleyez/plugins/routersploit_exploit.py +77 -55
  229. souleyez/plugins/searchsploit.py +91 -77
  230. souleyez/plugins/service_explorer.py +1160 -0
  231. souleyez/plugins/smbmap.py +122 -72
  232. souleyez/plugins/smbpasswd.py +215 -0
  233. souleyez/plugins/sqlmap.py +301 -113
  234. souleyez/plugins/theharvester.py +127 -75
  235. souleyez/plugins/tr069.py +79 -57
  236. souleyez/plugins/upnp.py +65 -47
  237. souleyez/plugins/upnp_abuse.py +73 -55
  238. souleyez/plugins/vnc_access.py +129 -42
  239. souleyez/plugins/vnc_brute.py +109 -38
  240. souleyez/plugins/web_login_test.py +417 -0
  241. souleyez/plugins/whois.py +77 -58
  242. souleyez/plugins/wpscan.py +173 -69
  243. souleyez/reporting/__init__.py +2 -1
  244. souleyez/reporting/attack_chain.py +411 -346
  245. souleyez/reporting/charts.py +436 -501
  246. souleyez/reporting/compliance_mappings.py +334 -201
  247. souleyez/reporting/detection_report.py +126 -125
  248. souleyez/reporting/formatters.py +828 -591
  249. souleyez/reporting/generator.py +386 -302
  250. souleyez/reporting/metrics.py +72 -75
  251. souleyez/scanner.py +35 -29
  252. souleyez/security/__init__.py +37 -11
  253. souleyez/security/scope_validator.py +175 -106
  254. souleyez/security/validation.py +223 -149
  255. souleyez/security.py +22 -6
  256. souleyez/storage/credentials.py +247 -186
  257. souleyez/storage/crypto.py +296 -129
  258. souleyez/storage/database.py +73 -50
  259. souleyez/storage/db.py +58 -36
  260. souleyez/storage/deliverable_evidence.py +177 -128
  261. souleyez/storage/deliverable_exporter.py +282 -246
  262. souleyez/storage/deliverable_templates.py +134 -116
  263. souleyez/storage/deliverables.py +135 -130
  264. souleyez/storage/engagements.py +109 -56
  265. souleyez/storage/evidence.py +181 -152
  266. souleyez/storage/execution_log.py +31 -17
  267. souleyez/storage/exploit_attempts.py +93 -57
  268. souleyez/storage/exploits.py +67 -36
  269. souleyez/storage/findings.py +48 -61
  270. souleyez/storage/hosts.py +176 -144
  271. souleyez/storage/migrate_to_engagements.py +43 -19
  272. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  273. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  274. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  275. souleyez/storage/migrations/_005_screenshots.py +13 -5
  276. souleyez/storage/migrations/_006_deliverables.py +13 -5
  277. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  278. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  279. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  280. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  281. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  282. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  283. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  284. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  285. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  286. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  287. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  288. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  289. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  290. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  291. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  292. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  293. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  294. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  295. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  296. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  297. souleyez/storage/migrations/__init__.py +26 -26
  298. souleyez/storage/migrations/migration_manager.py +19 -19
  299. souleyez/storage/msf_sessions.py +100 -65
  300. souleyez/storage/osint.py +17 -24
  301. souleyez/storage/recommendation_engine.py +269 -235
  302. souleyez/storage/screenshots.py +33 -32
  303. souleyez/storage/smb_shares.py +136 -92
  304. souleyez/storage/sqlmap_data.py +183 -128
  305. souleyez/storage/team_collaboration.py +135 -141
  306. souleyez/storage/timeline_tracker.py +122 -94
  307. souleyez/storage/wazuh_vulns.py +64 -66
  308. souleyez/storage/web_paths.py +33 -37
  309. souleyez/testing/credential_tester.py +221 -205
  310. souleyez/ui/__init__.py +1 -1
  311. souleyez/ui/ai_quotes.py +12 -12
  312. souleyez/ui/attack_surface.py +2439 -1516
  313. souleyez/ui/chain_rules_view.py +914 -382
  314. souleyez/ui/correlation_view.py +312 -230
  315. souleyez/ui/dashboard.py +2382 -1130
  316. souleyez/ui/deliverables_view.py +148 -62
  317. souleyez/ui/design_system.py +13 -13
  318. souleyez/ui/errors.py +49 -49
  319. souleyez/ui/evidence_linking_view.py +284 -179
  320. souleyez/ui/evidence_vault.py +393 -285
  321. souleyez/ui/exploit_suggestions_view.py +555 -349
  322. souleyez/ui/export_view.py +100 -66
  323. souleyez/ui/gap_analysis_view.py +315 -171
  324. souleyez/ui/help_system.py +105 -97
  325. souleyez/ui/intelligence_view.py +436 -293
  326. souleyez/ui/interactive.py +22827 -10678
  327. souleyez/ui/interactive_selector.py +75 -68
  328. souleyez/ui/log_formatter.py +47 -39
  329. souleyez/ui/menu_components.py +22 -13
  330. souleyez/ui/msf_auxiliary_menu.py +184 -133
  331. souleyez/ui/pending_chains_view.py +336 -172
  332. souleyez/ui/progress_indicators.py +5 -3
  333. souleyez/ui/recommendations_view.py +195 -137
  334. souleyez/ui/rule_builder.py +343 -225
  335. souleyez/ui/setup_wizard.py +678 -284
  336. souleyez/ui/shortcuts.py +217 -165
  337. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  338. souleyez/ui/splunk_vulns_view.py +139 -86
  339. souleyez/ui/team_dashboard.py +498 -335
  340. souleyez/ui/template_selector.py +196 -105
  341. souleyez/ui/terminal.py +6 -6
  342. souleyez/ui/timeline_view.py +198 -127
  343. souleyez/ui/tool_setup.py +264 -164
  344. souleyez/ui/tutorial.py +202 -72
  345. souleyez/ui/tutorial_state.py +40 -40
  346. souleyez/ui/wazuh_vulns_view.py +235 -141
  347. souleyez/ui/wordlist_browser.py +260 -107
  348. souleyez/ui.py +464 -312
  349. souleyez/utils/tool_checker.py +427 -367
  350. souleyez/utils.py +33 -29
  351. souleyez/wordlists.py +134 -167
  352. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
  353. souleyez-2.43.34.dist-info/RECORD +443 -0
  354. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.29.dist-info/RECORD +0 -379
  356. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,9 @@ class EngagementManager:
13
13
  def __init__(self):
14
14
  self.db = get_db()
15
15
 
16
- def create(self, name: str, description: str = "", engagement_type: str = "custom") -> int:
16
+ def create(
17
+ self, name: str, description: str = "", engagement_type: str = "custom"
18
+ ) -> int:
17
19
  """Create new engagement with current user as owner."""
18
20
  # Check if engagement already exists
19
21
  existing = self.get(name)
@@ -22,48 +24,57 @@ class EngagementManager:
22
24
 
23
25
  # Get current user as owner
24
26
  from souleyez.auth import get_current_user
27
+
25
28
  user = get_current_user()
26
29
  owner_id = user.id if user else None
27
30
 
28
- eng_id = self.db.insert("engagements", {
29
- "name": name,
30
- "description": description,
31
- "engagement_type": engagement_type,
32
- "owner_id": owner_id
33
- })
31
+ eng_id = self.db.insert(
32
+ "engagements",
33
+ {
34
+ "name": name,
35
+ "description": description,
36
+ "engagement_type": engagement_type,
37
+ "owner_id": owner_id,
38
+ },
39
+ )
34
40
 
35
41
  # Audit log
36
42
  from souleyez.auth.audit import audit_log, AuditAction
43
+
37
44
  audit_log(
38
45
  AuditAction.ENGAGEMENT_CREATED,
39
46
  resource_type="engagement",
40
47
  resource_id=eng_id,
41
- details={"name": name, "type": engagement_type}
48
+ details={"name": name, "type": engagement_type},
42
49
  )
43
50
 
44
51
  return eng_id
45
52
 
46
- def create_engagement(self, name: str, description: str = "", engagement_type: str = "custom") -> int:
53
+ def create_engagement(
54
+ self, name: str, description: str = "", engagement_type: str = "custom"
55
+ ) -> int:
47
56
  """Alias for create() for compatibility."""
48
57
  return self.create(name, description, engagement_type)
49
58
 
50
59
  def list(self, user_filtered: bool = True) -> List[Dict[str, Any]]:
51
60
  """
52
61
  List engagements.
53
-
62
+
54
63
  Args:
55
64
  user_filtered: If True, only show engagements user has access to.
56
65
  If False, show all (for admin operations).
57
66
  """
58
67
  if not user_filtered:
59
68
  return self.db.execute("SELECT * FROM engagements ORDER BY created_at DESC")
60
-
69
+
61
70
  from souleyez.auth import get_current_user
71
+
62
72
  user = get_current_user()
63
73
  if not user:
64
74
  return []
65
-
75
+
66
76
  from souleyez.auth.engagement_access import EngagementAccessManager
77
+
67
78
  access_mgr = EngagementAccessManager(self.db.db_path)
68
79
  return access_mgr.get_accessible_engagements(user.id, user.role)
69
80
 
@@ -77,7 +88,9 @@ class EngagementManager:
77
88
 
78
89
  def get_by_id(self, engagement_id: int) -> Optional[Dict[str, Any]]:
79
90
  """Get engagement by ID."""
80
- return self.db.execute_one("SELECT * FROM engagements WHERE id = ?", (engagement_id,))
91
+ return self.db.execute_one(
92
+ "SELECT * FROM engagements WHERE id = ?", (engagement_id,)
93
+ )
81
94
 
82
95
  def update(self, engagement_id: int, fields: Dict[str, Any]) -> bool:
83
96
  """Update engagement fields."""
@@ -93,7 +106,7 @@ class EngagementManager:
93
106
 
94
107
  self.db.execute(
95
108
  f"UPDATE engagements SET {set_clauses}, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
96
- tuple(values)
109
+ tuple(values),
97
110
  )
98
111
  return True
99
112
 
@@ -104,7 +117,7 @@ class EngagementManager:
104
117
  return False
105
118
 
106
119
  ENGAGEMENT_FILE.parent.mkdir(parents=True, exist_ok=True)
107
- ENGAGEMENT_FILE.write_text(str(eng['id']))
120
+ ENGAGEMENT_FILE.write_text(str(eng["id"]))
108
121
  return True
109
122
 
110
123
  def get_current(self) -> Optional[Dict[str, Any]]:
@@ -128,7 +141,7 @@ class EngagementManager:
128
141
  # Reset to default engagement - use existing or create new
129
142
  default_eng = self.get("default")
130
143
  if default_eng:
131
- default_id = default_eng['id']
144
+ default_id = default_eng["id"]
132
145
  else:
133
146
  default_id = self.create("default", "Default engagement")
134
147
  self.set_current("default")
@@ -141,24 +154,32 @@ class EngagementManager:
141
154
  return False
142
155
 
143
156
  # Delete associated data in correct order (respecting foreign keys)
144
-
157
+
145
158
  # 1. Delete execution log entries for this engagement
146
- self.db.execute("DELETE FROM execution_log WHERE engagement_id = ?", (eng['id'],))
147
-
159
+ self.db.execute(
160
+ "DELETE FROM execution_log WHERE engagement_id = ?", (eng["id"],)
161
+ )
162
+
148
163
  # 2. Delete SQLi data (CASCADE chain: databases → tables → columns & dumped_data)
149
- self.db.execute("""
164
+ self.db.execute(
165
+ """
150
166
  DELETE FROM sqli_databases
151
167
  WHERE engagement_id = ?
152
- """, (eng['id'],))
153
-
168
+ """,
169
+ (eng["id"],),
170
+ )
171
+
154
172
  # 3. Delete screenshots (references engagement, host, finding)
155
- self.db.execute("DELETE FROM screenshots WHERE engagement_id = ?", (eng['id'],))
156
-
173
+ self.db.execute("DELETE FROM screenshots WHERE engagement_id = ?", (eng["id"],))
174
+
157
175
  # 4. Delete deliverables (references engagement_id)
158
- self.db.execute("DELETE FROM deliverables WHERE engagement_id = ?", (eng['id'],))
159
-
176
+ self.db.execute(
177
+ "DELETE FROM deliverables WHERE engagement_id = ?", (eng["id"],)
178
+ )
179
+
160
180
  # 5. Delete SMB files (references smb_shares)
161
- self.db.execute("""
181
+ self.db.execute(
182
+ """
162
183
  DELETE FROM smb_files
163
184
  WHERE share_id IN (
164
185
  SELECT id FROM smb_shares
@@ -166,54 +187,77 @@ class EngagementManager:
166
187
  SELECT id FROM hosts WHERE engagement_id = ?
167
188
  )
168
189
  )
169
- """, (eng['id'],))
170
-
190
+ """,
191
+ (eng["id"],),
192
+ )
193
+
171
194
  # 6. Delete SMB shares (references hosts)
172
- self.db.execute("""
195
+ self.db.execute(
196
+ """
173
197
  DELETE FROM smb_shares
174
198
  WHERE host_id IN (SELECT id FROM hosts WHERE engagement_id = ?)
175
- """, (eng['id'],))
176
-
199
+ """,
200
+ (eng["id"],),
201
+ )
202
+
177
203
  # 7. Delete web paths (references hosts)
178
- self.db.execute("""
204
+ self.db.execute(
205
+ """
179
206
  DELETE FROM web_paths
180
207
  WHERE host_id IN (SELECT id FROM hosts WHERE engagement_id = ?)
181
- """, (eng['id'],))
182
-
208
+ """,
209
+ (eng["id"],),
210
+ )
211
+
183
212
  # 8. Delete credentials (references hosts)
184
- self.db.execute("""
213
+ self.db.execute(
214
+ """
185
215
  DELETE FROM credentials
186
216
  WHERE host_id IN (SELECT id FROM hosts WHERE engagement_id = ?)
187
217
  OR engagement_id = ?
188
- """, (eng['id'], eng['id']))
189
-
218
+ """,
219
+ (eng["id"], eng["id"]),
220
+ )
221
+
190
222
  # 9. Delete findings (references engagement_id)
191
- self.db.execute("DELETE FROM findings WHERE engagement_id = ?", (eng['id'],))
192
-
223
+ self.db.execute("DELETE FROM findings WHERE engagement_id = ?", (eng["id"],))
224
+
193
225
  # 10. Delete OSINT data (references engagement_id)
194
- self.db.execute("DELETE FROM osint_data WHERE engagement_id = ?", (eng['id'],))
195
-
226
+ self.db.execute("DELETE FROM osint_data WHERE engagement_id = ?", (eng["id"],))
227
+
196
228
  # 11. Delete services (references hosts)
197
- self.db.execute("""
229
+ self.db.execute(
230
+ """
198
231
  DELETE FROM services
199
232
  WHERE host_id IN (SELECT id FROM hosts WHERE engagement_id = ?)
200
- """, (eng['id'],))
201
-
233
+ """,
234
+ (eng["id"],),
235
+ )
236
+
202
237
  # 12. Delete hosts (now all foreign key references are gone)
203
- self.db.execute("DELETE FROM hosts WHERE engagement_id = ?", (eng['id'],))
204
-
238
+ self.db.execute("DELETE FROM hosts WHERE engagement_id = ?", (eng["id"],))
239
+
205
240
  # 13. Finally delete the engagement itself
206
- self.db.execute("DELETE FROM engagements WHERE id = ?", (eng['id'],))
241
+ self.db.execute("DELETE FROM engagements WHERE id = ?", (eng["id"],))
207
242
 
208
243
  # Audit log
209
244
  from souleyez.auth.audit import audit_log, AuditAction
245
+
210
246
  audit_log(
211
247
  AuditAction.ENGAGEMENT_DELETED,
212
248
  resource_type="engagement",
213
- resource_id=eng['id'],
214
- details={"name": name}
249
+ resource_id=eng["id"],
250
+ details={"name": name},
215
251
  )
216
252
 
253
+ # Clean up orphaned pending chains for deleted engagement
254
+ try:
255
+ from souleyez.core.pending_chains import purge_orphaned_chains
256
+
257
+ purge_orphaned_chains()
258
+ except Exception:
259
+ pass # Non-critical cleanup
260
+
217
261
  return True
218
262
 
219
263
  def stats(self, engagement_id: int) -> Dict[str, int]:
@@ -221,19 +265,22 @@ class EngagementManager:
221
265
  # Only count live hosts (status='up')
222
266
  hosts = self.db.execute_one(
223
267
  "SELECT COUNT(*) as count FROM hosts WHERE engagement_id = ? AND status = 'up'",
224
- (engagement_id,)
268
+ (engagement_id,),
225
269
  )
226
270
  # Only count services on live hosts
227
271
  services = self.db.execute_one(
228
272
  "SELECT COUNT(*) as count FROM services WHERE host_id IN (SELECT id FROM hosts WHERE engagement_id = ? AND status = 'up')",
229
- (engagement_id,)
273
+ (engagement_id,),
274
+ )
275
+ findings = self.db.execute_one(
276
+ "SELECT COUNT(*) as count FROM findings WHERE engagement_id = ?",
277
+ (engagement_id,),
230
278
  )
231
- findings = self.db.execute_one("SELECT COUNT(*) as count FROM findings WHERE engagement_id = ?", (engagement_id,))
232
279
 
233
280
  return {
234
- "hosts": hosts['count'] if hosts else 0,
235
- "services": services['count'] if services else 0,
236
- "findings": findings['count'] if findings else 0,
281
+ "hosts": hosts["count"] if hosts else 0,
282
+ "services": services["count"] if services else 0,
283
+ "findings": findings["count"] if findings else 0,
237
284
  }
238
285
 
239
286
  # =========================================================================
@@ -243,32 +290,38 @@ class EngagementManager:
243
290
  def can_access(self, engagement_id: int) -> bool:
244
291
  """Check if current user can access this engagement."""
245
292
  from souleyez.auth import get_current_user
293
+
246
294
  user = get_current_user()
247
295
  if not user:
248
296
  return False
249
297
 
250
298
  from souleyez.auth.engagement_access import EngagementAccessManager
299
+
251
300
  access_mgr = EngagementAccessManager(self.db.db_path)
252
301
  return access_mgr.can_access(engagement_id, user.id, user.role)
253
302
 
254
303
  def can_edit(self, engagement_id: int) -> bool:
255
304
  """Check if current user can edit this engagement."""
256
305
  from souleyez.auth import get_current_user
306
+
257
307
  user = get_current_user()
258
308
  if not user:
259
309
  return False
260
310
 
261
311
  from souleyez.auth.engagement_access import EngagementAccessManager
312
+
262
313
  access_mgr = EngagementAccessManager(self.db.db_path)
263
314
  return access_mgr.can_edit(engagement_id, user.id, user.role)
264
315
 
265
316
  def can_delete_engagement(self, engagement_id: int) -> bool:
266
317
  """Check if current user can delete this engagement."""
267
318
  from souleyez.auth import get_current_user
319
+
268
320
  user = get_current_user()
269
321
  if not user:
270
322
  return False
271
323
 
272
324
  from souleyez.auth.engagement_access import EngagementAccessManager
325
+
273
326
  access_mgr = EngagementAccessManager(self.db.db_path)
274
327
  return access_mgr.can_delete(engagement_id, user.id, user.role)