souleyez 2.43.28__py3-none-any.whl → 2.43.32__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 (356) 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 +9592 -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 +1238 -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 +2198 -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 +288 -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/whois_handler.py +277 -0
  126. souleyez/handlers/wpscan_handler.py +554 -0
  127. souleyez/history.py +32 -16
  128. souleyez/importers/msf_importer.py +106 -75
  129. souleyez/importers/smart_importer.py +208 -147
  130. souleyez/integrations/siem/__init__.py +10 -10
  131. souleyez/integrations/siem/base.py +17 -18
  132. souleyez/integrations/siem/elastic.py +108 -122
  133. souleyez/integrations/siem/factory.py +207 -80
  134. souleyez/integrations/siem/googlesecops.py +146 -154
  135. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  136. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  137. souleyez/integrations/siem/sentinel.py +107 -109
  138. souleyez/integrations/siem/splunk.py +246 -212
  139. souleyez/integrations/siem/wazuh.py +65 -71
  140. souleyez/integrations/wazuh/__init__.py +5 -5
  141. souleyez/integrations/wazuh/client.py +70 -93
  142. souleyez/integrations/wazuh/config.py +85 -57
  143. souleyez/integrations/wazuh/host_mapper.py +28 -36
  144. souleyez/integrations/wazuh/sync.py +78 -68
  145. souleyez/intelligence/__init__.py +4 -5
  146. souleyez/intelligence/correlation_analyzer.py +309 -295
  147. souleyez/intelligence/exploit_knowledge.py +661 -623
  148. souleyez/intelligence/exploit_suggestions.py +159 -139
  149. souleyez/intelligence/gap_analyzer.py +132 -97
  150. souleyez/intelligence/gap_detector.py +251 -214
  151. souleyez/intelligence/sensitive_tables.py +266 -129
  152. souleyez/intelligence/service_parser.py +137 -123
  153. souleyez/intelligence/surface_analyzer.py +407 -268
  154. souleyez/intelligence/target_parser.py +159 -162
  155. souleyez/licensing/__init__.py +6 -6
  156. souleyez/licensing/validator.py +17 -19
  157. souleyez/log_config.py +79 -54
  158. souleyez/main.py +1505 -687
  159. souleyez/migrations/fix_job_counter.py +16 -14
  160. souleyez/parsers/bloodhound_parser.py +41 -39
  161. souleyez/parsers/crackmapexec_parser.py +178 -111
  162. souleyez/parsers/dalfox_parser.py +72 -77
  163. souleyez/parsers/dnsrecon_parser.py +103 -91
  164. souleyez/parsers/enum4linux_parser.py +183 -153
  165. souleyez/parsers/ffuf_parser.py +29 -25
  166. souleyez/parsers/gobuster_parser.py +301 -41
  167. souleyez/parsers/hashcat_parser.py +324 -79
  168. souleyez/parsers/http_fingerprint_parser.py +350 -103
  169. souleyez/parsers/hydra_parser.py +131 -111
  170. souleyez/parsers/impacket_parser.py +231 -178
  171. souleyez/parsers/john_parser.py +98 -86
  172. souleyez/parsers/katana_parser.py +316 -0
  173. souleyez/parsers/msf_parser.py +943 -498
  174. souleyez/parsers/nikto_parser.py +346 -65
  175. souleyez/parsers/nmap_parser.py +262 -174
  176. souleyez/parsers/nuclei_parser.py +40 -44
  177. souleyez/parsers/responder_parser.py +26 -26
  178. souleyez/parsers/searchsploit_parser.py +74 -74
  179. souleyez/parsers/service_explorer_parser.py +279 -0
  180. souleyez/parsers/smbmap_parser.py +180 -124
  181. souleyez/parsers/sqlmap_parser.py +434 -308
  182. souleyez/parsers/theharvester_parser.py +75 -57
  183. souleyez/parsers/whois_parser.py +135 -94
  184. souleyez/parsers/wpscan_parser.py +278 -190
  185. souleyez/plugins/afp.py +44 -36
  186. souleyez/plugins/afp_brute.py +114 -46
  187. souleyez/plugins/ard.py +48 -37
  188. souleyez/plugins/bloodhound.py +95 -61
  189. souleyez/plugins/certipy.py +303 -0
  190. souleyez/plugins/crackmapexec.py +186 -85
  191. souleyez/plugins/dalfox.py +120 -59
  192. souleyez/plugins/dns_hijack.py +146 -41
  193. souleyez/plugins/dnsrecon.py +97 -61
  194. souleyez/plugins/enum4linux.py +91 -66
  195. souleyez/plugins/evil_winrm.py +291 -0
  196. souleyez/plugins/ffuf.py +166 -90
  197. souleyez/plugins/firmware_extract.py +133 -29
  198. souleyez/plugins/gobuster.py +387 -190
  199. souleyez/plugins/gpp_extract.py +393 -0
  200. souleyez/plugins/hashcat.py +100 -73
  201. souleyez/plugins/http_fingerprint.py +854 -267
  202. souleyez/plugins/hydra.py +566 -200
  203. souleyez/plugins/impacket_getnpusers.py +117 -69
  204. souleyez/plugins/impacket_psexec.py +84 -64
  205. souleyez/plugins/impacket_secretsdump.py +103 -69
  206. souleyez/plugins/impacket_smbclient.py +89 -75
  207. souleyez/plugins/john.py +86 -69
  208. souleyez/plugins/katana.py +313 -0
  209. souleyez/plugins/kerbrute.py +237 -0
  210. souleyez/plugins/lfi_extract.py +541 -0
  211. souleyez/plugins/macos_ssh.py +117 -48
  212. souleyez/plugins/mdns.py +35 -30
  213. souleyez/plugins/msf_auxiliary.py +253 -130
  214. souleyez/plugins/msf_exploit.py +239 -161
  215. souleyez/plugins/nikto.py +134 -78
  216. souleyez/plugins/nmap.py +275 -91
  217. souleyez/plugins/nuclei.py +180 -89
  218. souleyez/plugins/nxc.py +285 -0
  219. souleyez/plugins/plugin_base.py +35 -36
  220. souleyez/plugins/plugin_template.py +13 -5
  221. souleyez/plugins/rdp_sec_check.py +130 -0
  222. souleyez/plugins/responder.py +112 -71
  223. souleyez/plugins/router_http_brute.py +76 -65
  224. souleyez/plugins/router_ssh_brute.py +118 -41
  225. souleyez/plugins/router_telnet_brute.py +124 -42
  226. souleyez/plugins/routersploit.py +91 -59
  227. souleyez/plugins/routersploit_exploit.py +77 -55
  228. souleyez/plugins/searchsploit.py +91 -77
  229. souleyez/plugins/service_explorer.py +1160 -0
  230. souleyez/plugins/smbmap.py +122 -72
  231. souleyez/plugins/smbpasswd.py +215 -0
  232. souleyez/plugins/sqlmap.py +301 -113
  233. souleyez/plugins/theharvester.py +127 -75
  234. souleyez/plugins/tr069.py +79 -57
  235. souleyez/plugins/upnp.py +65 -47
  236. souleyez/plugins/upnp_abuse.py +73 -55
  237. souleyez/plugins/vnc_access.py +129 -42
  238. souleyez/plugins/vnc_brute.py +109 -38
  239. souleyez/plugins/whois.py +77 -58
  240. souleyez/plugins/wpscan.py +173 -69
  241. souleyez/reporting/__init__.py +2 -1
  242. souleyez/reporting/attack_chain.py +411 -346
  243. souleyez/reporting/charts.py +436 -501
  244. souleyez/reporting/compliance_mappings.py +334 -201
  245. souleyez/reporting/detection_report.py +126 -125
  246. souleyez/reporting/formatters.py +828 -591
  247. souleyez/reporting/generator.py +386 -302
  248. souleyez/reporting/metrics.py +72 -75
  249. souleyez/scanner.py +35 -29
  250. souleyez/security/__init__.py +37 -11
  251. souleyez/security/scope_validator.py +175 -106
  252. souleyez/security/validation.py +223 -149
  253. souleyez/security.py +22 -6
  254. souleyez/storage/credentials.py +247 -186
  255. souleyez/storage/crypto.py +296 -129
  256. souleyez/storage/database.py +73 -50
  257. souleyez/storage/db.py +58 -36
  258. souleyez/storage/deliverable_evidence.py +177 -128
  259. souleyez/storage/deliverable_exporter.py +282 -246
  260. souleyez/storage/deliverable_templates.py +134 -116
  261. souleyez/storage/deliverables.py +135 -130
  262. souleyez/storage/engagements.py +109 -56
  263. souleyez/storage/evidence.py +181 -152
  264. souleyez/storage/execution_log.py +31 -17
  265. souleyez/storage/exploit_attempts.py +93 -57
  266. souleyez/storage/exploits.py +67 -36
  267. souleyez/storage/findings.py +48 -61
  268. souleyez/storage/hosts.py +176 -144
  269. souleyez/storage/migrate_to_engagements.py +43 -19
  270. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  271. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  272. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  273. souleyez/storage/migrations/_005_screenshots.py +13 -5
  274. souleyez/storage/migrations/_006_deliverables.py +13 -5
  275. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  276. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  277. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  278. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  279. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  280. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  281. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  282. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  283. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  284. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  285. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  286. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  287. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  288. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  289. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  290. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  291. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  292. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  293. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  294. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  295. souleyez/storage/migrations/__init__.py +26 -26
  296. souleyez/storage/migrations/migration_manager.py +19 -19
  297. souleyez/storage/msf_sessions.py +100 -65
  298. souleyez/storage/osint.py +17 -24
  299. souleyez/storage/recommendation_engine.py +269 -235
  300. souleyez/storage/screenshots.py +33 -32
  301. souleyez/storage/smb_shares.py +136 -92
  302. souleyez/storage/sqlmap_data.py +183 -128
  303. souleyez/storage/team_collaboration.py +135 -141
  304. souleyez/storage/timeline_tracker.py +122 -94
  305. souleyez/storage/wazuh_vulns.py +64 -66
  306. souleyez/storage/web_paths.py +33 -37
  307. souleyez/testing/credential_tester.py +221 -205
  308. souleyez/ui/__init__.py +1 -1
  309. souleyez/ui/ai_quotes.py +12 -12
  310. souleyez/ui/attack_surface.py +2439 -1516
  311. souleyez/ui/chain_rules_view.py +914 -382
  312. souleyez/ui/correlation_view.py +312 -230
  313. souleyez/ui/dashboard.py +2382 -1130
  314. souleyez/ui/deliverables_view.py +148 -62
  315. souleyez/ui/design_system.py +13 -13
  316. souleyez/ui/errors.py +49 -49
  317. souleyez/ui/evidence_linking_view.py +284 -179
  318. souleyez/ui/evidence_vault.py +393 -285
  319. souleyez/ui/exploit_suggestions_view.py +555 -349
  320. souleyez/ui/export_view.py +100 -66
  321. souleyez/ui/gap_analysis_view.py +315 -171
  322. souleyez/ui/help_system.py +105 -97
  323. souleyez/ui/intelligence_view.py +436 -293
  324. souleyez/ui/interactive.py +23142 -10430
  325. souleyez/ui/interactive_selector.py +75 -68
  326. souleyez/ui/log_formatter.py +47 -39
  327. souleyez/ui/menu_components.py +22 -13
  328. souleyez/ui/msf_auxiliary_menu.py +184 -133
  329. souleyez/ui/pending_chains_view.py +336 -172
  330. souleyez/ui/progress_indicators.py +5 -3
  331. souleyez/ui/recommendations_view.py +195 -137
  332. souleyez/ui/rule_builder.py +343 -225
  333. souleyez/ui/setup_wizard.py +678 -284
  334. souleyez/ui/shortcuts.py +217 -165
  335. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  336. souleyez/ui/splunk_vulns_view.py +139 -86
  337. souleyez/ui/team_dashboard.py +498 -335
  338. souleyez/ui/template_selector.py +196 -105
  339. souleyez/ui/terminal.py +6 -6
  340. souleyez/ui/timeline_view.py +198 -127
  341. souleyez/ui/tool_setup.py +264 -164
  342. souleyez/ui/tutorial.py +202 -72
  343. souleyez/ui/tutorial_state.py +40 -40
  344. souleyez/ui/wazuh_vulns_view.py +235 -141
  345. souleyez/ui/wordlist_browser.py +260 -107
  346. souleyez/ui.py +464 -312
  347. souleyez/utils/tool_checker.py +427 -367
  348. souleyez/utils.py +33 -29
  349. souleyez/wordlists.py +134 -167
  350. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/METADATA +1 -1
  351. souleyez-2.43.32.dist-info/RECORD +441 -0
  352. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/WHEEL +1 -1
  353. souleyez-2.43.28.dist-info/RECORD +0 -379
  354. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/entry_points.txt +0 -0
  355. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/licenses/LICENSE +0 -0
  356. {souleyez-2.43.28.dist-info → souleyez-2.43.32.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)