regscale-cli 6.16.0.0__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.

Potentially problematic release.


This version of regscale-cli might be problematic. Click here for more details.

Files changed (481) hide show
  1. regscale/__init__.py +1 -0
  2. regscale/airflow/__init__.py +9 -0
  3. regscale/airflow/azure/__init__.py +9 -0
  4. regscale/airflow/azure/cli.py +89 -0
  5. regscale/airflow/azure/upload_dags.py +116 -0
  6. regscale/airflow/click_dags.py +127 -0
  7. regscale/airflow/click_mixins.py +82 -0
  8. regscale/airflow/config.py +25 -0
  9. regscale/airflow/factories/__init__.py +0 -0
  10. regscale/airflow/factories/connections.py +58 -0
  11. regscale/airflow/factories/workflows.py +78 -0
  12. regscale/airflow/hierarchy.py +88 -0
  13. regscale/airflow/operators/__init__.py +0 -0
  14. regscale/airflow/operators/click.py +36 -0
  15. regscale/airflow/sensors/__init__.py +0 -0
  16. regscale/airflow/sensors/sql.py +107 -0
  17. regscale/airflow/sessions/__init__.py +0 -0
  18. regscale/airflow/sessions/sql/__init__.py +3 -0
  19. regscale/airflow/sessions/sql/queries.py +64 -0
  20. regscale/airflow/sessions/sql/sql_server_queries.py +248 -0
  21. regscale/airflow/tasks/__init__.py +0 -0
  22. regscale/airflow/tasks/branches.py +22 -0
  23. regscale/airflow/tasks/cli.py +116 -0
  24. regscale/airflow/tasks/click.py +73 -0
  25. regscale/airflow/tasks/debugging.py +9 -0
  26. regscale/airflow/tasks/groups.py +116 -0
  27. regscale/airflow/tasks/init.py +60 -0
  28. regscale/airflow/tasks/states.py +47 -0
  29. regscale/airflow/tasks/workflows.py +36 -0
  30. regscale/ansible/__init__.py +9 -0
  31. regscale/core/__init__.py +0 -0
  32. regscale/core/app/__init__.py +3 -0
  33. regscale/core/app/api.py +571 -0
  34. regscale/core/app/application.py +665 -0
  35. regscale/core/app/internal/__init__.py +136 -0
  36. regscale/core/app/internal/admin_actions.py +230 -0
  37. regscale/core/app/internal/assessments_editor.py +873 -0
  38. regscale/core/app/internal/catalog.py +316 -0
  39. regscale/core/app/internal/comparison.py +459 -0
  40. regscale/core/app/internal/control_editor.py +571 -0
  41. regscale/core/app/internal/encrypt.py +79 -0
  42. regscale/core/app/internal/evidence.py +1240 -0
  43. regscale/core/app/internal/file_uploads.py +151 -0
  44. regscale/core/app/internal/healthcheck.py +66 -0
  45. regscale/core/app/internal/login.py +305 -0
  46. regscale/core/app/internal/migrations.py +240 -0
  47. regscale/core/app/internal/model_editor.py +1701 -0
  48. regscale/core/app/internal/poam_editor.py +632 -0
  49. regscale/core/app/internal/workflow.py +105 -0
  50. regscale/core/app/logz.py +74 -0
  51. regscale/core/app/utils/XMLIR.py +258 -0
  52. regscale/core/app/utils/__init__.py +0 -0
  53. regscale/core/app/utils/api_handler.py +358 -0
  54. regscale/core/app/utils/app_utils.py +1110 -0
  55. regscale/core/app/utils/catalog_utils/__init__.py +0 -0
  56. regscale/core/app/utils/catalog_utils/common.py +91 -0
  57. regscale/core/app/utils/catalog_utils/compare_catalog.py +193 -0
  58. regscale/core/app/utils/catalog_utils/diagnostic_catalog.py +97 -0
  59. regscale/core/app/utils/catalog_utils/download_catalog.py +103 -0
  60. regscale/core/app/utils/catalog_utils/update_catalog.py +718 -0
  61. regscale/core/app/utils/catalog_utils/update_catalog_v2.py +1378 -0
  62. regscale/core/app/utils/catalog_utils/update_catalog_v3.py +1272 -0
  63. regscale/core/app/utils/catalog_utils/update_plans.py +334 -0
  64. regscale/core/app/utils/file_utils.py +238 -0
  65. regscale/core/app/utils/parser_utils.py +81 -0
  66. regscale/core/app/utils/pickle_file_handler.py +57 -0
  67. regscale/core/app/utils/regscale_utils.py +319 -0
  68. regscale/core/app/utils/report_utils.py +119 -0
  69. regscale/core/app/utils/variables.py +226 -0
  70. regscale/core/decorators.py +31 -0
  71. regscale/core/lazy_group.py +65 -0
  72. regscale/core/login.py +63 -0
  73. regscale/core/server/__init__.py +0 -0
  74. regscale/core/server/flask_api.py +473 -0
  75. regscale/core/server/helpers.py +373 -0
  76. regscale/core/server/rest.py +64 -0
  77. regscale/core/server/static/css/bootstrap.css +6030 -0
  78. regscale/core/server/static/css/bootstrap.min.css +6 -0
  79. regscale/core/server/static/css/main.css +176 -0
  80. regscale/core/server/static/images/regscale-cli.svg +49 -0
  81. regscale/core/server/static/images/regscale.svg +38 -0
  82. regscale/core/server/templates/base.html +74 -0
  83. regscale/core/server/templates/index.html +43 -0
  84. regscale/core/server/templates/login.html +28 -0
  85. regscale/core/server/templates/make_base64.html +22 -0
  86. regscale/core/server/templates/upload_STIG.html +109 -0
  87. regscale/core/server/templates/upload_STIG_result.html +26 -0
  88. regscale/core/server/templates/upload_ssp.html +144 -0
  89. regscale/core/server/templates/upload_ssp_result.html +128 -0
  90. regscale/core/static/__init__.py +0 -0
  91. regscale/core/static/regex.py +14 -0
  92. regscale/core/utils/__init__.py +117 -0
  93. regscale/core/utils/click_utils.py +13 -0
  94. regscale/core/utils/date.py +238 -0
  95. regscale/core/utils/graphql.py +254 -0
  96. regscale/core/utils/urls.py +23 -0
  97. regscale/dev/__init__.py +6 -0
  98. regscale/dev/analysis.py +454 -0
  99. regscale/dev/cli.py +235 -0
  100. regscale/dev/code_gen.py +492 -0
  101. regscale/dev/dirs.py +69 -0
  102. regscale/dev/docs.py +384 -0
  103. regscale/dev/monitoring.py +26 -0
  104. regscale/dev/profiling.py +216 -0
  105. regscale/exceptions/__init__.py +4 -0
  106. regscale/exceptions/license_exception.py +7 -0
  107. regscale/exceptions/validation_exception.py +9 -0
  108. regscale/integrations/__init__.py +1 -0
  109. regscale/integrations/commercial/__init__.py +486 -0
  110. regscale/integrations/commercial/ad.py +433 -0
  111. regscale/integrations/commercial/amazon/__init__.py +0 -0
  112. regscale/integrations/commercial/amazon/common.py +106 -0
  113. regscale/integrations/commercial/aqua/__init__.py +0 -0
  114. regscale/integrations/commercial/aqua/aqua.py +91 -0
  115. regscale/integrations/commercial/aws/__init__.py +6 -0
  116. regscale/integrations/commercial/aws/cli.py +322 -0
  117. regscale/integrations/commercial/aws/inventory/__init__.py +110 -0
  118. regscale/integrations/commercial/aws/inventory/base.py +64 -0
  119. regscale/integrations/commercial/aws/inventory/resources/__init__.py +19 -0
  120. regscale/integrations/commercial/aws/inventory/resources/compute.py +234 -0
  121. regscale/integrations/commercial/aws/inventory/resources/containers.py +113 -0
  122. regscale/integrations/commercial/aws/inventory/resources/database.py +101 -0
  123. regscale/integrations/commercial/aws/inventory/resources/integration.py +237 -0
  124. regscale/integrations/commercial/aws/inventory/resources/networking.py +253 -0
  125. regscale/integrations/commercial/aws/inventory/resources/security.py +240 -0
  126. regscale/integrations/commercial/aws/inventory/resources/storage.py +91 -0
  127. regscale/integrations/commercial/aws/scanner.py +823 -0
  128. regscale/integrations/commercial/azure/__init__.py +0 -0
  129. regscale/integrations/commercial/azure/common.py +32 -0
  130. regscale/integrations/commercial/azure/intune.py +488 -0
  131. regscale/integrations/commercial/azure/scanner.py +49 -0
  132. regscale/integrations/commercial/burp.py +78 -0
  133. regscale/integrations/commercial/cpe.py +144 -0
  134. regscale/integrations/commercial/crowdstrike.py +1117 -0
  135. regscale/integrations/commercial/defender.py +1511 -0
  136. regscale/integrations/commercial/dependabot.py +210 -0
  137. regscale/integrations/commercial/durosuite/__init__.py +0 -0
  138. regscale/integrations/commercial/durosuite/api.py +1546 -0
  139. regscale/integrations/commercial/durosuite/process_devices.py +101 -0
  140. regscale/integrations/commercial/durosuite/scanner.py +637 -0
  141. regscale/integrations/commercial/durosuite/variables.py +21 -0
  142. regscale/integrations/commercial/ecr.py +90 -0
  143. regscale/integrations/commercial/gcp/__init__.py +237 -0
  144. regscale/integrations/commercial/gcp/auth.py +96 -0
  145. regscale/integrations/commercial/gcp/control_tests.py +238 -0
  146. regscale/integrations/commercial/gcp/variables.py +18 -0
  147. regscale/integrations/commercial/gitlab.py +332 -0
  148. regscale/integrations/commercial/grype.py +165 -0
  149. regscale/integrations/commercial/ibm.py +90 -0
  150. regscale/integrations/commercial/import_all/__init__.py +0 -0
  151. regscale/integrations/commercial/import_all/import_all_cmd.py +467 -0
  152. regscale/integrations/commercial/import_all/scan_file_fingerprints.json +27 -0
  153. regscale/integrations/commercial/jira.py +1046 -0
  154. regscale/integrations/commercial/mappings/__init__.py +0 -0
  155. regscale/integrations/commercial/mappings/csf_controls.json +713 -0
  156. regscale/integrations/commercial/mappings/nist_800_53_r5_controls.json +1516 -0
  157. regscale/integrations/commercial/nessus/__init__.py +0 -0
  158. regscale/integrations/commercial/nessus/nessus_utils.py +429 -0
  159. regscale/integrations/commercial/nessus/scanner.py +416 -0
  160. regscale/integrations/commercial/nexpose.py +90 -0
  161. regscale/integrations/commercial/okta.py +798 -0
  162. regscale/integrations/commercial/opentext/__init__.py +0 -0
  163. regscale/integrations/commercial/opentext/click.py +99 -0
  164. regscale/integrations/commercial/opentext/scanner.py +143 -0
  165. regscale/integrations/commercial/prisma.py +91 -0
  166. regscale/integrations/commercial/qualys.py +1462 -0
  167. regscale/integrations/commercial/salesforce.py +980 -0
  168. regscale/integrations/commercial/sap/__init__.py +0 -0
  169. regscale/integrations/commercial/sap/click.py +31 -0
  170. regscale/integrations/commercial/sap/sysdig/__init__.py +0 -0
  171. regscale/integrations/commercial/sap/sysdig/click.py +57 -0
  172. regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +190 -0
  173. regscale/integrations/commercial/sap/tenable/__init__.py +0 -0
  174. regscale/integrations/commercial/sap/tenable/click.py +49 -0
  175. regscale/integrations/commercial/sap/tenable/scanner.py +196 -0
  176. regscale/integrations/commercial/servicenow.py +1756 -0
  177. regscale/integrations/commercial/sicura/__init__.py +0 -0
  178. regscale/integrations/commercial/sicura/api.py +855 -0
  179. regscale/integrations/commercial/sicura/commands.py +73 -0
  180. regscale/integrations/commercial/sicura/scanner.py +481 -0
  181. regscale/integrations/commercial/sicura/variables.py +16 -0
  182. regscale/integrations/commercial/snyk.py +90 -0
  183. regscale/integrations/commercial/sonarcloud.py +260 -0
  184. regscale/integrations/commercial/sqlserver.py +369 -0
  185. regscale/integrations/commercial/stig_mapper_integration/__init__.py +0 -0
  186. regscale/integrations/commercial/stig_mapper_integration/click_commands.py +38 -0
  187. regscale/integrations/commercial/stig_mapper_integration/mapping_engine.py +353 -0
  188. regscale/integrations/commercial/stigv2/__init__.py +0 -0
  189. regscale/integrations/commercial/stigv2/ckl_parser.py +349 -0
  190. regscale/integrations/commercial/stigv2/click_commands.py +95 -0
  191. regscale/integrations/commercial/stigv2/stig_integration.py +202 -0
  192. regscale/integrations/commercial/synqly/__init__.py +0 -0
  193. regscale/integrations/commercial/synqly/assets.py +46 -0
  194. regscale/integrations/commercial/synqly/ticketing.py +132 -0
  195. regscale/integrations/commercial/synqly/vulnerabilities.py +223 -0
  196. regscale/integrations/commercial/synqly_jira.py +840 -0
  197. regscale/integrations/commercial/tenablev2/__init__.py +0 -0
  198. regscale/integrations/commercial/tenablev2/authenticate.py +31 -0
  199. regscale/integrations/commercial/tenablev2/click.py +1584 -0
  200. regscale/integrations/commercial/tenablev2/scanner.py +504 -0
  201. regscale/integrations/commercial/tenablev2/stig_parsers.py +140 -0
  202. regscale/integrations/commercial/tenablev2/utils.py +78 -0
  203. regscale/integrations/commercial/tenablev2/variables.py +17 -0
  204. regscale/integrations/commercial/trivy.py +162 -0
  205. regscale/integrations/commercial/veracode.py +96 -0
  206. regscale/integrations/commercial/wizv2/WizDataMixin.py +97 -0
  207. regscale/integrations/commercial/wizv2/__init__.py +0 -0
  208. regscale/integrations/commercial/wizv2/click.py +429 -0
  209. regscale/integrations/commercial/wizv2/constants.py +1001 -0
  210. regscale/integrations/commercial/wizv2/issue.py +361 -0
  211. regscale/integrations/commercial/wizv2/models.py +112 -0
  212. regscale/integrations/commercial/wizv2/parsers.py +339 -0
  213. regscale/integrations/commercial/wizv2/sbom.py +115 -0
  214. regscale/integrations/commercial/wizv2/scanner.py +416 -0
  215. regscale/integrations/commercial/wizv2/utils.py +796 -0
  216. regscale/integrations/commercial/wizv2/variables.py +39 -0
  217. regscale/integrations/commercial/wizv2/wiz_auth.py +159 -0
  218. regscale/integrations/commercial/xray.py +91 -0
  219. regscale/integrations/integration/__init__.py +2 -0
  220. regscale/integrations/integration/integration.py +26 -0
  221. regscale/integrations/integration/inventory.py +17 -0
  222. regscale/integrations/integration/issue.py +100 -0
  223. regscale/integrations/integration_override.py +149 -0
  224. regscale/integrations/public/__init__.py +103 -0
  225. regscale/integrations/public/cisa.py +641 -0
  226. regscale/integrations/public/criticality_updater.py +70 -0
  227. regscale/integrations/public/emass.py +411 -0
  228. regscale/integrations/public/emass_slcm_import.py +697 -0
  229. regscale/integrations/public/fedramp/__init__.py +0 -0
  230. regscale/integrations/public/fedramp/appendix_parser.py +548 -0
  231. regscale/integrations/public/fedramp/click.py +479 -0
  232. regscale/integrations/public/fedramp/components.py +714 -0
  233. regscale/integrations/public/fedramp/docx_parser.py +259 -0
  234. regscale/integrations/public/fedramp/fedramp_cis_crm.py +1124 -0
  235. regscale/integrations/public/fedramp/fedramp_common.py +3181 -0
  236. regscale/integrations/public/fedramp/fedramp_docx.py +388 -0
  237. regscale/integrations/public/fedramp/fedramp_five.py +2343 -0
  238. regscale/integrations/public/fedramp/fedramp_traversal.py +138 -0
  239. regscale/integrations/public/fedramp/import_fedramp_r4_ssp.py +279 -0
  240. regscale/integrations/public/fedramp/import_workbook.py +495 -0
  241. regscale/integrations/public/fedramp/inventory_items.py +244 -0
  242. regscale/integrations/public/fedramp/mappings/__init__.py +0 -0
  243. regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +7388 -0
  244. regscale/integrations/public/fedramp/mappings/fedramp_r5_params.json +8636 -0
  245. regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +9605 -0
  246. regscale/integrations/public/fedramp/mappings/system_roles.py +34 -0
  247. regscale/integrations/public/fedramp/mappings/user.py +175 -0
  248. regscale/integrations/public/fedramp/mappings/values.py +141 -0
  249. regscale/integrations/public/fedramp/markdown_parser.py +150 -0
  250. regscale/integrations/public/fedramp/metadata.py +689 -0
  251. regscale/integrations/public/fedramp/models/__init__.py +59 -0
  252. regscale/integrations/public/fedramp/models/leveraged_auth_new.py +168 -0
  253. regscale/integrations/public/fedramp/models/poam_importer.py +522 -0
  254. regscale/integrations/public/fedramp/parts_mapper.py +107 -0
  255. regscale/integrations/public/fedramp/poam/__init__.py +0 -0
  256. regscale/integrations/public/fedramp/poam/scanner.py +851 -0
  257. regscale/integrations/public/fedramp/properties.py +201 -0
  258. regscale/integrations/public/fedramp/reporting.py +84 -0
  259. regscale/integrations/public/fedramp/resources.py +496 -0
  260. regscale/integrations/public/fedramp/rosetta.py +110 -0
  261. regscale/integrations/public/fedramp/ssp_logger.py +87 -0
  262. regscale/integrations/public/fedramp/system_characteristics.py +922 -0
  263. regscale/integrations/public/fedramp/system_control_implementations.py +582 -0
  264. regscale/integrations/public/fedramp/system_implementation.py +190 -0
  265. regscale/integrations/public/fedramp/xml_utils.py +87 -0
  266. regscale/integrations/public/nist_catalog.py +275 -0
  267. regscale/integrations/public/oscal.py +1946 -0
  268. regscale/integrations/public/otx.py +169 -0
  269. regscale/integrations/scanner_integration.py +2692 -0
  270. regscale/integrations/variables.py +25 -0
  271. regscale/models/__init__.py +7 -0
  272. regscale/models/app_models/__init__.py +5 -0
  273. regscale/models/app_models/catalog_compare.py +213 -0
  274. regscale/models/app_models/click.py +252 -0
  275. regscale/models/app_models/datetime_encoder.py +21 -0
  276. regscale/models/app_models/import_validater.py +321 -0
  277. regscale/models/app_models/mapping.py +260 -0
  278. regscale/models/app_models/pipeline.py +37 -0
  279. regscale/models/click_models.py +413 -0
  280. regscale/models/config.py +154 -0
  281. regscale/models/email_style.css +67 -0
  282. regscale/models/hierarchy.py +8 -0
  283. regscale/models/inspect_models.py +79 -0
  284. regscale/models/integration_models/__init__.py +0 -0
  285. regscale/models/integration_models/amazon_models/__init__.py +0 -0
  286. regscale/models/integration_models/amazon_models/inspector.py +262 -0
  287. regscale/models/integration_models/amazon_models/inspector_scan.py +206 -0
  288. regscale/models/integration_models/aqua.py +247 -0
  289. regscale/models/integration_models/azure_alerts.py +255 -0
  290. regscale/models/integration_models/base64.py +23 -0
  291. regscale/models/integration_models/burp.py +433 -0
  292. regscale/models/integration_models/burp_models.py +128 -0
  293. regscale/models/integration_models/cisa_kev_data.json +19333 -0
  294. regscale/models/integration_models/defender_data.py +93 -0
  295. regscale/models/integration_models/defenderimport.py +143 -0
  296. regscale/models/integration_models/drf.py +443 -0
  297. regscale/models/integration_models/ecr_models/__init__.py +0 -0
  298. regscale/models/integration_models/ecr_models/data.py +69 -0
  299. regscale/models/integration_models/ecr_models/ecr.py +239 -0
  300. regscale/models/integration_models/flat_file_importer.py +1079 -0
  301. regscale/models/integration_models/grype_import.py +247 -0
  302. regscale/models/integration_models/ibm.py +126 -0
  303. regscale/models/integration_models/implementation_results.py +85 -0
  304. regscale/models/integration_models/nexpose.py +140 -0
  305. regscale/models/integration_models/prisma.py +202 -0
  306. regscale/models/integration_models/qualys.py +720 -0
  307. regscale/models/integration_models/qualys_scanner.py +160 -0
  308. regscale/models/integration_models/sbom/__init__.py +0 -0
  309. regscale/models/integration_models/sbom/cyclone_dx.py +139 -0
  310. regscale/models/integration_models/send_reminders.py +620 -0
  311. regscale/models/integration_models/snyk.py +155 -0
  312. regscale/models/integration_models/synqly_models/__init__.py +0 -0
  313. regscale/models/integration_models/synqly_models/capabilities.json +1 -0
  314. regscale/models/integration_models/synqly_models/connector_types.py +22 -0
  315. regscale/models/integration_models/synqly_models/connectors/__init__.py +7 -0
  316. regscale/models/integration_models/synqly_models/connectors/assets.py +97 -0
  317. regscale/models/integration_models/synqly_models/connectors/ticketing.py +583 -0
  318. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +169 -0
  319. regscale/models/integration_models/synqly_models/ocsf_mapper.py +331 -0
  320. regscale/models/integration_models/synqly_models/param.py +72 -0
  321. regscale/models/integration_models/synqly_models/synqly_model.py +733 -0
  322. regscale/models/integration_models/synqly_models/tenants.py +39 -0
  323. regscale/models/integration_models/tenable_models/__init__.py +0 -0
  324. regscale/models/integration_models/tenable_models/integration.py +187 -0
  325. regscale/models/integration_models/tenable_models/models.py +513 -0
  326. regscale/models/integration_models/trivy_import.py +231 -0
  327. regscale/models/integration_models/veracode.py +217 -0
  328. regscale/models/integration_models/xray.py +135 -0
  329. regscale/models/locking.py +100 -0
  330. regscale/models/platform.py +110 -0
  331. regscale/models/regscale_models/__init__.py +67 -0
  332. regscale/models/regscale_models/assessment.py +570 -0
  333. regscale/models/regscale_models/assessment_plan.py +52 -0
  334. regscale/models/regscale_models/asset.py +567 -0
  335. regscale/models/regscale_models/asset_mapping.py +190 -0
  336. regscale/models/regscale_models/case.py +42 -0
  337. regscale/models/regscale_models/catalog.py +261 -0
  338. regscale/models/regscale_models/cci.py +46 -0
  339. regscale/models/regscale_models/change.py +167 -0
  340. regscale/models/regscale_models/checklist.py +372 -0
  341. regscale/models/regscale_models/comment.py +49 -0
  342. regscale/models/regscale_models/compliance_settings.py +112 -0
  343. regscale/models/regscale_models/component.py +412 -0
  344. regscale/models/regscale_models/component_mapping.py +65 -0
  345. regscale/models/regscale_models/control.py +38 -0
  346. regscale/models/regscale_models/control_implementation.py +1128 -0
  347. regscale/models/regscale_models/control_objective.py +261 -0
  348. regscale/models/regscale_models/control_parameter.py +100 -0
  349. regscale/models/regscale_models/control_test.py +34 -0
  350. regscale/models/regscale_models/control_test_plan.py +75 -0
  351. regscale/models/regscale_models/control_test_result.py +52 -0
  352. regscale/models/regscale_models/custom_field.py +245 -0
  353. regscale/models/regscale_models/data.py +109 -0
  354. regscale/models/regscale_models/data_center.py +40 -0
  355. regscale/models/regscale_models/deviation.py +203 -0
  356. regscale/models/regscale_models/email.py +97 -0
  357. regscale/models/regscale_models/evidence.py +47 -0
  358. regscale/models/regscale_models/evidence_mapping.py +40 -0
  359. regscale/models/regscale_models/facility.py +59 -0
  360. regscale/models/regscale_models/file.py +382 -0
  361. regscale/models/regscale_models/filetag.py +37 -0
  362. regscale/models/regscale_models/form_field_value.py +94 -0
  363. regscale/models/regscale_models/group.py +169 -0
  364. regscale/models/regscale_models/implementation_objective.py +335 -0
  365. regscale/models/regscale_models/implementation_option.py +275 -0
  366. regscale/models/regscale_models/implementation_role.py +33 -0
  367. regscale/models/regscale_models/incident.py +177 -0
  368. regscale/models/regscale_models/interconnection.py +43 -0
  369. regscale/models/regscale_models/issue.py +1176 -0
  370. regscale/models/regscale_models/leveraged_authorization.py +125 -0
  371. regscale/models/regscale_models/line_of_inquiry.py +52 -0
  372. regscale/models/regscale_models/link.py +205 -0
  373. regscale/models/regscale_models/meta_data.py +64 -0
  374. regscale/models/regscale_models/mixins/__init__.py +0 -0
  375. regscale/models/regscale_models/mixins/parent_cache.py +124 -0
  376. regscale/models/regscale_models/module.py +224 -0
  377. regscale/models/regscale_models/modules.py +191 -0
  378. regscale/models/regscale_models/objective.py +14 -0
  379. regscale/models/regscale_models/parameter.py +87 -0
  380. regscale/models/regscale_models/ports_protocol.py +81 -0
  381. regscale/models/regscale_models/privacy.py +89 -0
  382. regscale/models/regscale_models/profile.py +50 -0
  383. regscale/models/regscale_models/profile_link.py +68 -0
  384. regscale/models/regscale_models/profile_mapping.py +124 -0
  385. regscale/models/regscale_models/project.py +63 -0
  386. regscale/models/regscale_models/property.py +278 -0
  387. regscale/models/regscale_models/question.py +85 -0
  388. regscale/models/regscale_models/questionnaire.py +87 -0
  389. regscale/models/regscale_models/questionnaire_instance.py +177 -0
  390. regscale/models/regscale_models/rbac.py +132 -0
  391. regscale/models/regscale_models/reference.py +86 -0
  392. regscale/models/regscale_models/regscale_model.py +1643 -0
  393. regscale/models/regscale_models/requirement.py +29 -0
  394. regscale/models/regscale_models/risk.py +274 -0
  395. regscale/models/regscale_models/sbom.py +54 -0
  396. regscale/models/regscale_models/scan_history.py +436 -0
  397. regscale/models/regscale_models/search.py +53 -0
  398. regscale/models/regscale_models/security_control.py +132 -0
  399. regscale/models/regscale_models/security_plan.py +204 -0
  400. regscale/models/regscale_models/software_inventory.py +159 -0
  401. regscale/models/regscale_models/stake_holder.py +64 -0
  402. regscale/models/regscale_models/stig.py +647 -0
  403. regscale/models/regscale_models/supply_chain.py +152 -0
  404. regscale/models/regscale_models/system_role.py +188 -0
  405. regscale/models/regscale_models/system_role_external_assignment.py +40 -0
  406. regscale/models/regscale_models/tag.py +37 -0
  407. regscale/models/regscale_models/tag_mapping.py +19 -0
  408. regscale/models/regscale_models/task.py +133 -0
  409. regscale/models/regscale_models/threat.py +196 -0
  410. regscale/models/regscale_models/user.py +175 -0
  411. regscale/models/regscale_models/user_group.py +55 -0
  412. regscale/models/regscale_models/vulnerability.py +242 -0
  413. regscale/models/regscale_models/vulnerability_mapping.py +162 -0
  414. regscale/models/regscale_models/workflow.py +55 -0
  415. regscale/models/regscale_models/workflow_action.py +34 -0
  416. regscale/models/regscale_models/workflow_instance.py +269 -0
  417. regscale/models/regscale_models/workflow_instance_step.py +114 -0
  418. regscale/models/regscale_models/workflow_template.py +58 -0
  419. regscale/models/regscale_models/workflow_template_step.py +45 -0
  420. regscale/regscale.py +815 -0
  421. regscale/utils/__init__.py +7 -0
  422. regscale/utils/b64conversion.py +14 -0
  423. regscale/utils/click_utils.py +118 -0
  424. regscale/utils/decorators.py +48 -0
  425. regscale/utils/dict_utils.py +59 -0
  426. regscale/utils/files.py +79 -0
  427. regscale/utils/fxns.py +30 -0
  428. regscale/utils/graphql_client.py +113 -0
  429. regscale/utils/lists.py +16 -0
  430. regscale/utils/numbers.py +12 -0
  431. regscale/utils/shell.py +148 -0
  432. regscale/utils/string.py +121 -0
  433. regscale/utils/synqly_utils.py +165 -0
  434. regscale/utils/threading/__init__.py +8 -0
  435. regscale/utils/threading/threadhandler.py +131 -0
  436. regscale/utils/threading/threadsafe_counter.py +47 -0
  437. regscale/utils/threading/threadsafe_dict.py +242 -0
  438. regscale/utils/threading/threadsafe_list.py +83 -0
  439. regscale/utils/version.py +104 -0
  440. regscale/validation/__init__.py +0 -0
  441. regscale/validation/address.py +37 -0
  442. regscale/validation/record.py +48 -0
  443. regscale/visualization/__init__.py +5 -0
  444. regscale/visualization/click.py +34 -0
  445. regscale_cli-6.16.0.0.dist-info/LICENSE +21 -0
  446. regscale_cli-6.16.0.0.dist-info/METADATA +659 -0
  447. regscale_cli-6.16.0.0.dist-info/RECORD +481 -0
  448. regscale_cli-6.16.0.0.dist-info/WHEEL +5 -0
  449. regscale_cli-6.16.0.0.dist-info/entry_points.txt +6 -0
  450. regscale_cli-6.16.0.0.dist-info/top_level.txt +2 -0
  451. tests/fixtures/__init__.py +2 -0
  452. tests/fixtures/api.py +87 -0
  453. tests/fixtures/models.py +91 -0
  454. tests/fixtures/test_fixture.py +144 -0
  455. tests/mocks/__init__.py +0 -0
  456. tests/mocks/objects.py +3 -0
  457. tests/mocks/response.py +32 -0
  458. tests/mocks/xml.py +13 -0
  459. tests/regscale/__init__.py +0 -0
  460. tests/regscale/core/__init__.py +0 -0
  461. tests/regscale/core/test_api.py +232 -0
  462. tests/regscale/core/test_app.py +406 -0
  463. tests/regscale/core/test_login.py +37 -0
  464. tests/regscale/core/test_logz.py +66 -0
  465. tests/regscale/core/test_sbom_generator.py +87 -0
  466. tests/regscale/core/test_validation_utils.py +163 -0
  467. tests/regscale/core/test_version.py +78 -0
  468. tests/regscale/models/__init__.py +0 -0
  469. tests/regscale/models/test_asset.py +71 -0
  470. tests/regscale/models/test_config.py +26 -0
  471. tests/regscale/models/test_control_implementation.py +27 -0
  472. tests/regscale/models/test_import.py +97 -0
  473. tests/regscale/models/test_issue.py +36 -0
  474. tests/regscale/models/test_mapping.py +52 -0
  475. tests/regscale/models/test_platform.py +31 -0
  476. tests/regscale/models/test_regscale_model.py +346 -0
  477. tests/regscale/models/test_report.py +32 -0
  478. tests/regscale/models/test_tenable_integrations.py +118 -0
  479. tests/regscale/models/test_user_model.py +121 -0
  480. tests/regscale/test_about.py +19 -0
  481. tests/regscale/test_authorization.py +65 -0
@@ -0,0 +1,152 @@
1
+ """Supply Chain model class"""
2
+
3
+ import logging
4
+ from enum import Enum
5
+ from typing import Optional, Union
6
+
7
+ from pydantic import ConfigDict, Field
8
+
9
+ from .regscale_model import RegScaleModel
10
+
11
+ logger = logging.getLogger("regscale")
12
+
13
+
14
+ class SupplyChainStatus(str, Enum):
15
+ """Supply Chain Status"""
16
+
17
+ Pending = "Pending"
18
+ Active = "Active"
19
+ Closed = "Closed"
20
+
21
+ def __str__(self) -> str:
22
+ """
23
+ Return the string representation of the Supply Chain Status
24
+
25
+ :return: The string representation of the Supply Chain Status
26
+ :rtype: str
27
+ """
28
+ return self.value
29
+
30
+
31
+ class SupplyChainTier(str, Enum):
32
+ """Supply Chain Tier"""
33
+
34
+ Tier1 = "Tier 1 - Organizational"
35
+ Tier2 = "Tier 2 - Mission"
36
+ Tier3 = "Tier 3 - Information System"
37
+ Tier4 = "Tier 4 - Administrative/Other"
38
+
39
+ def __str__(self) -> str:
40
+ """
41
+ Return the string representation of the Supply Chain Tier
42
+
43
+ :return: The string representation of the Supply Chain Tier
44
+ :rtype: str
45
+ """
46
+ return self.value
47
+
48
+
49
+ class SupplyChainFipsImpact(str, Enum):
50
+ """Supply Chain Fips Impact Level"""
51
+
52
+ Low = "Low"
53
+ Moderate = "Moderate"
54
+ High = "High"
55
+
56
+ def __str__(self) -> str:
57
+ """
58
+ Return the string representation of the Supply Chain Fips Impact Level
59
+
60
+ :return: The string representation of the Supply Chain Fips Impact Level
61
+ :rtype: str
62
+ """
63
+ return self.value
64
+
65
+
66
+ class SupplyChainContractType(str, Enum):
67
+ """Supply Chain Contract Type"""
68
+
69
+ FirmFixedPrice = "Firm Fixed Price (FFP)"
70
+ TimeAndMaterials = "Time and Materials (T&M)"
71
+ CostPlus = "Cost Plus"
72
+ Subcontractor = "Subcontractor"
73
+
74
+ def __str__(self) -> str:
75
+ """
76
+ Return the string representation of the Supply Chain Contract Type
77
+
78
+ :return: The string representation of the Supply Chain Contract Type
79
+ :rtype: str
80
+ """
81
+ return self.value
82
+
83
+
84
+ class SupplyChain(RegScaleModel):
85
+ """Supply Chain model class"""
86
+
87
+ _parent_id_field = "parentId"
88
+ _unique_fields = [
89
+ ["parentId", "parentModule", "contractNumber"],
90
+ ]
91
+ _module_slug = "supplychain"
92
+
93
+ title: str
94
+ id: Optional[int] = 0
95
+ status: Union[SupplyChainStatus, str] = SupplyChainStatus.Pending
96
+ uuid: Optional[str] = None
97
+ fips: Optional[Union[SupplyChainFipsImpact, str]] = None
98
+ contractNumber: Optional[str] = None
99
+ isPublic: bool = True
100
+ parentId: int = 0
101
+ parentModule: Optional[str] = None
102
+ orgId: Optional[int] = 0
103
+ facilityId: Optional[int] = 0
104
+ contractValue: Optional[int] = 0
105
+ fundedAmount: Optional[int] = 0
106
+ actualCosts: Optional[int] = 0
107
+ strategicTier: Optional[Union[SupplyChainTier, str]] = None
108
+ contractType: Optional[Union[SupplyChainContractType, str]] = None
109
+ scope: Optional[str] = (None,)
110
+ startDate: Optional[str] = None
111
+ endDate: Optional[str] = None
112
+ violationURL: Optional[str] = None
113
+ stockURL: Optional[str] = None
114
+ duns: Optional[str] = None
115
+ ein: Optional[str] = None
116
+ cageCodes: Optional[str] = None
117
+ naics: Optional[str] = None
118
+ stockSymbol: Optional[str] = None
119
+ aribaNetworkId: Optional[str] = None
120
+ contractOwnerId: str = Field(default_factory=RegScaleModel._get_api_handler().get_user_id)
121
+
122
+ @staticmethod
123
+ def _get_additional_endpoints() -> ConfigDict:
124
+ """
125
+ Get additional endpoints for the SupplyChain model.
126
+
127
+ :return: A dictionary of additional endpoints
128
+ :rtype: ConfigDict
129
+ """
130
+ return ConfigDict(
131
+ get_list="/api/{model_slug}/list",
132
+ get_count="/api/{model_slug}/getCount",
133
+ get_all_by_parent="/api/{model_slug}/getAllByParent/intParentId/{strModule}",
134
+ graph="/api/{model_slug}/graph",
135
+ graph_contrat_amount="/api/{model_slug}/graphContractAmount/{year}",
136
+ graph_status_by_month="/api/{model_slug}/graphStatusByMonth/{year}",
137
+ graph_by_date="/api/{model_slug}/graphByDate/{strGroupBy}/{year}",
138
+ filter_supplychain="/api/{model_slug}/filterSupplyChain",
139
+ query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
140
+ statusboard="/api/{model_slug}/statusboard/{strSearch}/{strStatus}/{strType}/{strOwner}/{facilityId}/{intPage}/{intPageSize}",
141
+ find_by_uuid="/api/{model_slug}/findByUUID/{strUUID}",
142
+ find_by_ariba_id="/api/{model_slug}/findByAribaId/{strAriba}",
143
+ find_by_stock_symbol="/api/{model_slug}/findByStockSymbol/{strStock}",
144
+ find_by_naic="/api/{model_slug}/findByNAIC/{strNAIC}",
145
+ find_by_cage_code="/api/{model_slug}/findByCageCode/{strCAGE}",
146
+ find_by_ein="/api/{model_slug}/findByEIN/{strEIN}",
147
+ find_by_duns="/api/{model_slug}/findByDUNS/{strDUNS}",
148
+ main_dashboard="/api/{model_slug}/mainDashboard/{intYear}",
149
+ dashboard="/api/{model_slug}/dashboard/{strGroupBy}",
150
+ report="/api/{model_slug}/report/{strReport}",
151
+ schedule="/api/{model_slug}/schedule/{year}/{dvar}",
152
+ )
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Class for a RegScale SystemRoles"""
4
+ import copy
5
+ import logging
6
+ from typing import List, Optional
7
+ from typing import cast
8
+ from urllib.parse import urljoin
9
+
10
+ import requests
11
+ from pydantic import Field, ConfigDict
12
+
13
+ from regscale.core.app.api import Api
14
+ from regscale.core.app.application import Application
15
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
16
+
17
+ logger = logging.getLogger("regscale")
18
+
19
+
20
+ class SystemRole(RegScaleModel):
21
+ """Class for a RegScale SystemRoles"""
22
+
23
+ _module_slug = "systemRoles"
24
+
25
+ roleName: str # Required Field
26
+ roleType: str # Required Field
27
+ accessLevel: str # Required Field
28
+ sensitivityLevel: str # Required field
29
+ privilegeDescription: str # Required Field
30
+ securityPlanId: int # Required Field
31
+ functions: str # Required Field
32
+ createdById: str = Field(default_factory=RegScaleModel.get_user_id)
33
+ id: int = 0
34
+ uuid: str = ""
35
+ lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
36
+ isPublic: bool = True
37
+ dateCreated: Optional[str] = None
38
+ dateLastUpdated: Optional[str] = None
39
+ assignedUserId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
40
+ fedrampRoleId: Optional[str] = None
41
+ tenantsId: int = 1
42
+ externalUserId: Optional[str] = None
43
+
44
+ @staticmethod
45
+ def _get_additional_endpoints() -> ConfigDict:
46
+ """
47
+ Get additional endpoints for the SystemRole
48
+
49
+ :return: Additional endpoints for the SystemRole
50
+ :rtype: ConfigDict
51
+ """
52
+ return ConfigDict( # type: ignore
53
+ get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentID}",
54
+ )
55
+
56
+ @staticmethod
57
+ def from_dict(obj: dict) -> "SystemRole": # type: ignore
58
+ """
59
+ Create a SystemRoles object from a dictionary
60
+
61
+ :param dict obj: The dictionary to convert to a SystemRoles object
62
+ :return: A SystemRoles object
63
+ :rtype: SystemRole
64
+ """
65
+ copy_obj = copy.copy(obj)
66
+ if "id" in copy_obj:
67
+ del copy_obj["id"]
68
+ if isinstance(copy_obj["functions"], list):
69
+ copy_obj["functions"] = ", ".join(copy_obj["functions"])
70
+ return SystemRole(**copy_obj)
71
+
72
+ def __eq__(self, other: "SystemRole") -> bool:
73
+ """
74
+ Compare two SystemRoles objects
75
+
76
+ :param SystemRole other: The object to compare to
77
+ :return: True if the SystemRoles objects are equal
78
+ :rtype: bool
79
+ """
80
+ if not isinstance(other, SystemRole):
81
+ return NotImplemented
82
+ return self.dict() == other.dict()
83
+
84
+ def __hash__(self) -> hash:
85
+ """
86
+ Hash a SystemRoles object
87
+
88
+ :return: The hash of the SystemRoles object
89
+ :rtype: hash
90
+ """
91
+ return hash(
92
+ (
93
+ self.roleName,
94
+ self.roleType,
95
+ self.accessLevel,
96
+ self.sensitivityLevel,
97
+ self.privilegeDescription,
98
+ tuple(self.functions),
99
+ self.securityPlanId,
100
+ self.isPublic,
101
+ self.assignedUserId,
102
+ self.fedrampRoleId,
103
+ )
104
+ )
105
+
106
+ def insert_systemrole(self, app: Application) -> dict:
107
+ """
108
+ Insert a SystemRoles object into the database
109
+
110
+ :param Application app: The application object
111
+ :return: The dict of the SystemRoles object
112
+ :rtype: dict
113
+ """
114
+ # Convert the object to a dictionary
115
+ api = Api()
116
+ url = urljoin(app.config.get("domain", ""), "/api/systemRoles/")
117
+ if hasattr(self, "id"):
118
+ del self.id
119
+ if hasattr(self, "uuid"):
120
+ del self.uuid
121
+ if hasattr(self, "dateCreated"):
122
+ del self.dateCreated
123
+ data = self.dict()
124
+ # Make the API call
125
+ try:
126
+ response = api.post(url, json=data)
127
+ if response.ok:
128
+ # Parse the response to a SystemRoles object
129
+ logger.info(
130
+ "Successfully saved System Role %s to RegScale Security" + " Plan %i",
131
+ data["roleName"],
132
+ data["securityPlanId"],
133
+ )
134
+ return response.json()
135
+ except requests.exceptions.RequestException as err:
136
+ logger.warning(
137
+ "Unable to post System Role to RegScale Security Plan #%i, \n%s",
138
+ self.securityPlanId,
139
+ err,
140
+ )
141
+ return {}
142
+
143
+ @classmethod
144
+ def get_or_create(cls, app: Application, role_name: str, ssp_id: int, **kwargs) -> dict:
145
+ """
146
+ Get or create a SystemRoles object for a given SSP ID
147
+
148
+ :param Application app: The application object
149
+ :param str role_name: The name of the role
150
+ :param int ssp_id: The SSP ID
151
+ :param **kwargs: Additional keyword arguments
152
+ :return: The SystemRoles dict object
153
+ :rtype: dict
154
+ """
155
+
156
+ # Check if a role with the same name already exists
157
+ if "all_roles" not in kwargs:
158
+ all_roles = cls.get_all_by_ssp_id(app, ssp_id)
159
+ else:
160
+ all_roles = kwargs["all_roles"]
161
+
162
+ existing_role = next(
163
+ (role for role in all_roles if role["roleName"].lower().strip() == role_name.lower().strip()),
164
+ None,
165
+ )
166
+ if existing_role:
167
+ logger.debug("Role: %s already exists in RegScale, skipping insert..", role_name.strip())
168
+ return existing_role
169
+ else:
170
+ # If it doesn't exist, create a new one
171
+ new_role = cls(roleName=role_name.strip(), **kwargs)
172
+ return new_role.insert_systemrole(app=app)
173
+
174
+ @staticmethod
175
+ def get_all_by_ssp_id(app: Application, ssp_id: int) -> List["SystemRole"]:
176
+ """
177
+ Get a list of SystemRoles objects for a given SSP ID
178
+
179
+ :param Application app: The application object
180
+ :param int ssp_id: The SSP ID
181
+ :return: A list of SystemRoles objects
182
+ :rtype: List[SystemRole]
183
+ """
184
+ api = Api()
185
+ url = urljoin(app.config.get("domain", ""), f"/api/systemRoles/getAllByParent/{ssp_id}")
186
+ response = api.get(url)
187
+ # Parse the response to a list of SystemRoles objects
188
+ return cast(List[SystemRole], [role for role in response.json()] if response.json() else [])
@@ -0,0 +1,40 @@
1
+ """Provide a SystemRoleExternalAssignments model."""
2
+
3
+ import warnings
4
+ from typing import Optional
5
+ from urllib.parse import urljoin
6
+
7
+ from regscale.core.app.api import Api
8
+ from regscale.core.app.application import Application
9
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
10
+
11
+
12
+ class SystemRoleExternalAssignment(RegScaleModel):
13
+ """SystemRoleExternalAssignments model"""
14
+
15
+ _module_slug = "systemRoleExternalAssignments"
16
+
17
+ id: int = 0
18
+ uuid: str = ""
19
+ stakeholderId: int = 0
20
+ roleId: int = 0
21
+
22
+ def post(self, app: Application) -> Optional["SystemRoleExternalAssignment"]:
23
+ """
24
+ Post a SystemRoleExternalAssignments to RegScale
25
+
26
+ This method is deprecated, use 'create' method instead
27
+
28
+ :param Application app: The application instance
29
+ :return: The response from the API or None
30
+ :rtype: Optional[SystemRoleExternalAssignment]
31
+ """
32
+ warnings.warn(
33
+ "The 'post' method is deprecated, use 'create' method instead",
34
+ DeprecationWarning,
35
+ )
36
+ api = Api()
37
+ url = urljoin(app.config.get("domain", ""), "/api/systemRoleExternalAssignments")
38
+ data = self.dict()
39
+ response = api.post(url, json=data)
40
+ return SystemRoleExternalAssignment(**response.json()) if response.ok else None
@@ -0,0 +1,37 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from pydantic import Field
5
+
6
+ from regscale.core.app.utils.app_utils import get_current_datetime
7
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
8
+
9
+
10
+ class TagTypeEnum(Enum):
11
+ """
12
+ TagTypeEnum class
13
+ """
14
+
15
+ SYSTEM = "System"
16
+ EXPORT = "Export"
17
+ IMPORT = "Import"
18
+ DATA = "Data"
19
+ USER = "User"
20
+
21
+
22
+ class Tag(RegScaleModel):
23
+ _module_slug = "tags"
24
+
25
+ id: int = 0
26
+ uuid: Optional[str] = None
27
+ title: str = "" # required
28
+ tagType: TagTypeEnum = TagTypeEnum.USER.value # default to user. Use System for Export or Import
29
+ isPublic: bool = True
30
+ OscalRequired: bool = False
31
+ tagColor: Optional[str] = None # not currently implemented yet
32
+ tagTextColor: Optional[str] = None # not currently implemented yet
33
+ tenantsId: int = 1
34
+ createdById: str = Field(default_factory=RegScaleModel.get_user_id)
35
+ dateCreated: str = Field(default_factory=get_current_datetime)
36
+ lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
37
+ dateLastUpdated: str = Field(default_factory=get_current_datetime)
@@ -0,0 +1,19 @@
1
+ from pydantic import Field
2
+
3
+ from regscale.core.app.utils.app_utils import get_current_datetime
4
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
5
+
6
+
7
+ class TagMapping(RegScaleModel):
8
+ _module_slug = "tagMappings"
9
+
10
+ id: int = 0
11
+ parentId: str = ""
12
+ parentModule: str = ""
13
+ tagId: int = 0
14
+ isPublic: bool = True
15
+ tenantsId: int = 1
16
+ createdById: str = Field(default_factory=RegScaleModel.get_user_id)
17
+ dateCreated: str = Field(default_factory=get_current_datetime)
18
+ lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
19
+ dateLastUpdated: str = Field(default_factory=get_current_datetime)
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Task in the application"""
4
+
5
+ from typing import Optional, List
6
+
7
+ from pydantic import ConfigDict, Field, field_validator
8
+
9
+ from regscale.core.app.utils.app_utils import get_current_datetime
10
+ from regscale.core.utils.date import date_str
11
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
12
+
13
+
14
+ class Task(RegScaleModel):
15
+ """
16
+ Task model class
17
+ """
18
+
19
+ _module_slug = "tasks"
20
+ _unique_fields = [
21
+ ["title", "description", "parentID", "parentModule"],
22
+ ]
23
+ status: str # Required
24
+ title: str # Required
25
+ dueDate: str # Required
26
+ id: int = 0 # Required
27
+ uuid: Optional[str] = None
28
+ otherIdentifier: Optional[str] = None
29
+ taskType: Optional[str] = None
30
+ assignedToId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
31
+ description: Optional[str] = None
32
+ results: Optional[str] = None
33
+ originalDueDate: Optional[str] = None
34
+ dateSlide: Optional[int] = None
35
+ dateClosed: Optional[str] = None
36
+ percentComplete: Optional[int] = None
37
+ statusUpdate: Optional[str] = None
38
+ orgId: Optional[int] = None
39
+ levelOfEffort: Optional[int] = None
40
+ parentId: Optional[int] = None
41
+ parentModule: Optional[str] = None
42
+ isPublic: bool = True
43
+ createdById: str = Field(default_factory=RegScaleModel.get_user_id) # FK to AspNetUsers
44
+ dateCreated: str = Field(default_factory=get_current_datetime) # Required
45
+ lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id) # FK to AspNetUsers
46
+ dateLastUpdated: str = Field(default_factory=get_current_datetime) # Required
47
+
48
+ @staticmethod
49
+ def _get_additional_endpoints() -> ConfigDict:
50
+ """
51
+ Get additional endpoints for the Task model.
52
+
53
+ :return: A dictionary of additional endpoints
54
+ :rtype: ConfigDict
55
+ """
56
+ return ConfigDict( # type: ignore
57
+ get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentID}/{strModule}",
58
+ create="/api/{model_slug}",
59
+ other_identifier_starts_with="/api/{model_slug}/otherIdentifierStartsWith/{strId}",
60
+ query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
61
+ get_by_date_range="/api/{model_slug}/getByDateRangeAll/{dtStart}/{dtEnd}",
62
+ )
63
+
64
+ @classmethod
65
+ def query_by_custom_field(cls, field_name: str, field_value: str) -> List["Task"]:
66
+ """
67
+ Query tasks by a custom field.
68
+
69
+ :param str field_name: The name of the custom field to query
70
+ :param str field_value: The value of the custom field to match
71
+ :return: A list of Task instances matching the query
72
+ :rtype: List[Task]
73
+ """
74
+ endpoint = cls.get_endpoint("query_by_custom_field").format(strFieldName=field_name, strValue=field_value)
75
+ response = cls._get_api_handler().get(endpoint=endpoint)
76
+ return cls._handle_list_response(response)
77
+
78
+ @classmethod
79
+ def get_by_date_range(cls, start_date: str, end_date: str) -> List["Task"]:
80
+ """
81
+ Query tasks within a specified date range.
82
+
83
+ :param str start_date: The start date of the range
84
+ :param str end_date: The end date of the range
85
+ :return: A list of Task instances within the specified date range
86
+ :rtype: List[Task]
87
+ """
88
+
89
+ endpoint = cls.get_endpoint("get_by_date_range").format(dtStart=date_str(start_date), dtEnd=date_str(end_date))
90
+ response = cls._get_api_handler().get(endpoint=endpoint)
91
+ return cls._handle_list_response(response)
92
+
93
+ def __eq__(self, other: "Task") -> bool:
94
+ """
95
+ Equality of items in Task class
96
+
97
+ :param Task other: Task object to compare to
98
+ :return: Whether the two tasks are equal
99
+ :rtype: bool
100
+ """
101
+ return (
102
+ self.title == other.title
103
+ and self.otherIdentifier == other.otherIdentifier
104
+ and self.description == other.description
105
+ and self.parentId == other.parentId
106
+ and self.parentModule == other.parentModule
107
+ )
108
+
109
+ def __hash__(self) -> int:
110
+ """
111
+ Hash function for Task class
112
+
113
+ :return: Hash of the Task object
114
+ :rtype: int
115
+ """
116
+
117
+ return hash((self.title, self.description, self.parentId, self.parentModule, self.otherIdentifier))
118
+
119
+ @field_validator("status", mode="before")
120
+ @classmethod
121
+ def validate_status(cls, v: str) -> str:
122
+ """
123
+ Validate the status of the task
124
+
125
+ :param str v: The status of the task
126
+ :raises ValueError: If the status is not one of the allowed values
127
+ :return: The status of the task
128
+ :rtype: str
129
+
130
+ """
131
+ if v not in ["Backlog", "Open", "Closed", "Cancelled"]:
132
+ raise ValueError("Task status must be either 'Backlog', 'Open', 'Closed', or 'Cancelled'")
133
+ return v