howler-api 4.1.0.dev1436__tar.gz → 4.1.0.dev1460__tar.gz

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 (227) hide show
  1. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/PKG-INFO +1 -1
  2. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/search.py +8 -2
  3. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/action_queue_worker.py +3 -3
  4. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/action_service.py +22 -16
  5. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/search_service.py +20 -2
  6. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/pyproject.toml +1 -1
  7. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/README.md +0 -0
  8. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/__init__.py +0 -0
  9. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/__init__.py +0 -0
  10. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/add_label.py +0 -0
  11. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/add_to_bundle.py +0 -0
  12. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/add_to_case.py +0 -0
  13. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/change_field.py +0 -0
  14. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/demote.py +0 -0
  15. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/example_plugin.py +0 -0
  16. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/prioritization.py +0 -0
  17. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/promote.py +0 -0
  18. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/remove_from_bundle.py +0 -0
  19. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/remove_label.py +0 -0
  20. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/transition.py +0 -0
  21. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/__init__.py +0 -0
  22. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/base.py +0 -0
  23. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/socket.py +0 -0
  24. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/__init__.py +0 -0
  25. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/action.py +0 -0
  26. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/analytic.py +0 -0
  27. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/auth.py +0 -0
  28. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/clue.py +0 -0
  29. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/configs.py +0 -0
  30. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/dossier.py +0 -0
  31. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/help.py +0 -0
  32. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/hit.py +0 -0
  33. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/notebook.py +0 -0
  34. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/overview.py +0 -0
  35. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/search.py +0 -0
  36. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/template.py +0 -0
  37. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/tool.py +0 -0
  38. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/user.py +0 -0
  39. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/utils/__init__.py +0 -0
  40. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/utils/etag.py +0 -0
  41. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/utils/params.py +0 -0
  42. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/view.py +0 -0
  43. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/__init__.py +0 -0
  44. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/case.py +0 -0
  45. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/fuzzy.py +0 -0
  46. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/ingest.py +0 -0
  47. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/app.py +0 -0
  48. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/README.md +0 -0
  49. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/__init__.py +0 -0
  50. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/classification.py +0 -0
  51. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/classification.yml +0 -0
  52. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/exceptions.py +0 -0
  53. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/loader.py +0 -0
  54. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/logging/__init__.py +0 -0
  55. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/logging/audit.py +0 -0
  56. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/logging/format.py +0 -0
  57. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/net.py +0 -0
  58. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/net_static.py +0 -0
  59. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/random_user.py +0 -0
  60. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/swagger.py +0 -0
  61. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/config.py +0 -0
  62. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/__init__.py +0 -0
  63. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/correlation.py +0 -0
  64. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/retention.py +0 -0
  65. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/view_cleanup.py +0 -0
  66. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/README.md +0 -0
  67. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/__init__.py +0 -0
  68. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/bulk.py +0 -0
  69. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/collection.py +0 -0
  70. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/constants.py +0 -0
  71. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/exceptions.py +0 -0
  72. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/howler_store.py +0 -0
  73. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/migrations/fix_process.py +0 -0
  74. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/operations.py +0 -0
  75. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/schemas.py +0 -0
  76. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/store.py +0 -0
  77. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/support/__init__.py +0 -0
  78. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/support/build.py +0 -0
  79. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/support/schemas.py +0 -0
  80. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/types.py +0 -0
  81. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/utils.py +0 -0
  82. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/error.py +0 -0
  83. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/README.md +0 -0
  84. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/__init__.py +0 -0
  85. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/check_duplicates.py +0 -0
  86. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_mitre.py +0 -0
  87. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_sigma_rules.py +0 -0
  88. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_tlds.py +0 -0
  89. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/reindex_data.py +0 -0
  90. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/wipe_databases.py +0 -0
  91. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/gunicorn_config.py +0 -0
  92. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/healthz.py +0 -0
  93. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/__init__.py +0 -0
  94. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/azure.py +0 -0
  95. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/discover.py +0 -0
  96. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/hit.py +0 -0
  97. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/oauth.py +0 -0
  98. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/search.py +0 -0
  99. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/workflow.py +0 -0
  100. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/ws.py +0 -0
  101. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/README.md +0 -0
  102. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/__init__.py +0 -0
  103. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/base.py +0 -0
  104. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/charter.txt +0 -0
  105. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/constants.py +0 -0
  106. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/helper.py +0 -0
  107. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/howler_enum.py +0 -0
  108. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/mixins.py +0 -0
  109. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/__init__.py +0 -0
  110. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/action.py +0 -0
  111. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/analytic.py +0 -0
  112. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/assemblyline.py +0 -0
  113. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/aws.py +0 -0
  114. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/azure.py +0 -0
  115. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/case.py +0 -0
  116. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/cbs.py +0 -0
  117. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/clue.py +0 -0
  118. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/config.py +0 -0
  119. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/dossier.py +0 -0
  120. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/__init__.py +0 -0
  121. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/agent.py +0 -0
  122. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/autonomous_system.py +0 -0
  123. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/client.py +0 -0
  124. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/cloud.py +0 -0
  125. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/code_signature.py +0 -0
  126. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/container.py +0 -0
  127. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/dns.py +0 -0
  128. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/egress.py +0 -0
  129. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/elf.py +0 -0
  130. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/email.py +0 -0
  131. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/error.py +0 -0
  132. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/event.py +0 -0
  133. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/faas.py +0 -0
  134. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/file.py +0 -0
  135. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/geo.py +0 -0
  136. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/group.py +0 -0
  137. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/hash.py +0 -0
  138. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/host.py +0 -0
  139. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/http.py +0 -0
  140. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/ingress.py +0 -0
  141. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/interface.py +0 -0
  142. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/network.py +0 -0
  143. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/observer.py +0 -0
  144. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/organization.py +0 -0
  145. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/os.py +0 -0
  146. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/pe.py +0 -0
  147. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/process.py +0 -0
  148. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/registry.py +0 -0
  149. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/related.py +0 -0
  150. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/rule.py +0 -0
  151. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/server.py +0 -0
  152. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/threat.py +0 -0
  153. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/tls.py +0 -0
  154. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/url.py +0 -0
  155. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/user.py +0 -0
  156. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/user_agent.py +0 -0
  157. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/vulnerability.py +0 -0
  158. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/event.py +0 -0
  159. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/gcp.py +0 -0
  160. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/hit.py +0 -0
  161. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/howler_data.py +0 -0
  162. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/lead.py +0 -0
  163. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/localized_label.py +0 -0
  164. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/overview.py +0 -0
  165. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/pivot.py +0 -0
  166. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/record.py +0 -0
  167. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/template.py +0 -0
  168. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/user.py +0 -0
  169. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/view.py +0 -0
  170. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/random_data.py +0 -0
  171. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/randomizer.py +0 -0
  172. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/patched.py +0 -0
  173. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/plugins/__init__.py +0 -0
  174. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/plugins/config.py +0 -0
  175. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/__init__.py +0 -0
  176. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/README.md +0 -0
  177. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/__init__.py +0 -0
  178. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/counters.py +0 -0
  179. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/events.py +0 -0
  180. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/hash.py +0 -0
  181. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/lock.py +0 -0
  182. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/__init__.py +0 -0
  183. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/comms.py +0 -0
  184. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/multi.py +0 -0
  185. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/named.py +0 -0
  186. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/priority.py +0 -0
  187. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/set.py +0 -0
  188. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  189. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/security/__init__.py +0 -0
  190. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/security/socket.py +0 -0
  191. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/security/utils.py +0 -0
  192. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/__init__.py +0 -0
  193. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/analytic_service.py +0 -0
  194. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/auth_service.py +0 -0
  195. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/bundle_compat_service.py +0 -0
  196. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/case_service.py +0 -0
  197. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/comms_service.py +0 -0
  198. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/config_service.py +0 -0
  199. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/correlation_service.py +0 -0
  200. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/docs_service.py +0 -0
  201. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/dossier_service.py +0 -0
  202. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/event_service.py +0 -0
  203. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/fuzzy_service.py +0 -0
  204. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/hit_service.py +0 -0
  205. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/jwt_service.py +0 -0
  206. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/lucene_service.py +0 -0
  207. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/notebook_service.py +0 -0
  208. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/overview_service.py +0 -0
  209. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/template_service.py +0 -0
  210. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/user_service.py +0 -0
  211. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/viewer_service.py +0 -0
  212. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/telemetry.py +0 -0
  213. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/__init__.py +0 -0
  214. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/annotations.py +0 -0
  215. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/chunk.py +0 -0
  216. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/compat.py +0 -0
  217. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/constants.py +0 -0
  218. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/dict_utils.py +0 -0
  219. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/indexes.py +0 -0
  220. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/isotime.py +0 -0
  221. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/list_utils.py +0 -0
  222. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/lucene.py +0 -0
  223. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/net_utils.py +0 -0
  224. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/path.py +0 -0
  225. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/socket_utils.py +0 -0
  226. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/str_utils.py +0 -0
  227. {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 4.1.0.dev1436
3
+ Version: 4.1.0.dev1460
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -7,7 +7,7 @@ from elasticsearch import BadRequestError
7
7
  from elasticsearch._sync.client.indices import IndicesClient
8
8
  from flask import request
9
9
 
10
- from howler.api import bad_request, internal_error, make_subapi_blueprint, ok
10
+ from howler.api import bad_request, forbidden, internal_error, make_subapi_blueprint, ok
11
11
  from howler.common.loader import datastore
12
12
  from howler.common.logging import get_logger
13
13
  from howler.common.logging.audit import audit
@@ -17,6 +17,7 @@ from howler.helper.search import get_collection, has_access_control
17
17
  from howler.odm.models.user import User
18
18
  from howler.security import api_login
19
19
  from howler.services import hit_service, lucene_service, search_service
20
+ from howler.services.search_service import SensitiveUserFieldsException
20
21
  from howler.utils.net_utils import generate_params
21
22
 
22
23
  SUB_API = "search"
@@ -98,7 +99,10 @@ def search(indexes: str, user: User, **kwargs):
98
99
  }
99
100
  )
100
101
 
101
- params["sort"] = [entry for entry in params.get("sort", "").split(",") if entry] or search_service.DEFAULT_SORT
102
+ if params.get("sort"):
103
+ params["sort"] = [entry for entry in params["sort"].split(",") if entry]
104
+ else:
105
+ params.pop("sort", None)
102
106
 
103
107
  query = req_data.get("query", None)
104
108
  if not query:
@@ -110,6 +114,8 @@ def search(indexes: str, user: User, **kwargs):
110
114
 
111
115
  try:
112
116
  result = search_service.search(indexes, query, user=user, **params)
117
+ except SensitiveUserFieldsException as e:
118
+ return forbidden(err=e.message)
113
119
  except (SearchException, BadRequestError) as e:
114
120
  logger.exception(f"SearchException on query {query}")
115
121
  return bad_request(err=f"SearchException on query {query}: {str(e)}")
@@ -13,7 +13,7 @@ from apscheduler.schedulers.base import BaseScheduler
13
13
  from howler.common.logging import get_logger
14
14
  from howler.config import config
15
15
  from howler.odm.models.action import VALID_TRIGGERS
16
- from howler.services.action_service import _get_action_queue, process_action_batch
16
+ from howler.services.action_service import TriggeredAction, get_action_queue, process_action_batch
17
17
 
18
18
  logger = get_logger(__file__)
19
19
 
@@ -33,7 +33,7 @@ def run_worker(trigger: str) -> None: # pragma: no cover – long-running loop,
33
33
  logger.info("Action queue worker disabled by configuration, not starting for trigger=%s", trigger)
34
34
  return
35
35
 
36
- queue = _get_action_queue(trigger)
36
+ queue = get_action_queue(trigger)
37
37
  logger.info(
38
38
  "Action queue worker started for trigger=%s (batch_size=%d, timeout=%ds)",
39
39
  trigger,
@@ -41,7 +41,7 @@ def run_worker(trigger: str) -> None: # pragma: no cover – long-running loop,
41
41
  BATCH_TIMEOUT,
42
42
  )
43
43
 
44
- batch: list[dict] = []
44
+ batch: list[TriggeredAction] = []
45
45
 
46
46
  while True:
47
47
  try:
@@ -1,5 +1,6 @@
1
1
  import json
2
- from typing import Any, Optional
2
+ from collections import defaultdict
3
+ from typing import Any, Optional, TypedDict
3
4
 
4
5
  from flask import Response
5
6
 
@@ -18,11 +19,19 @@ from howler.utils.str_utils import sanitize_lucene_query
18
19
 
19
20
  logger = get_logger(__file__)
20
21
 
22
+
23
+ class TriggeredAction(TypedDict):
24
+ """Type for triggered actions"""
25
+
26
+ hit_ids: list[str]
27
+ uname: str | None
28
+
29
+
21
30
  # Per-trigger persistent queues for buffering action execution requests.
22
- _action_queues: dict[str, NamedQueue[dict]] = {}
31
+ _action_queues: dict[str, NamedQueue[TriggeredAction]] = {}
23
32
 
24
33
 
25
- def _get_action_queue(trigger: str) -> NamedQueue[dict]:
34
+ def get_action_queue(trigger: str) -> NamedQueue[TriggeredAction]:
26
35
  """Return the action queue for *trigger*, creating it on first use.
27
36
 
28
37
  Raises:
@@ -65,10 +74,10 @@ def enqueue_action_execution(hit_ids: list[str], trigger: str = "create", user:
65
74
  return
66
75
 
67
76
  try:
68
- _get_action_queue(trigger).push(
77
+ get_action_queue(trigger).push(
69
78
  {
70
79
  "hit_ids": hit_ids,
71
- "user": user.as_primitives() if user is not None and hasattr(user, "as_primitives") else user,
80
+ "uname": user.uname if user else None,
72
81
  }
73
82
  )
74
83
  except Exception:
@@ -77,7 +86,7 @@ def enqueue_action_execution(hit_ids: list[str], trigger: str = "create", user:
77
86
  bulk_execute_on_query(query, trigger=trigger, user=user)
78
87
 
79
88
 
80
- def process_action_batch(trigger: str, items: list[dict]) -> None:
89
+ def process_action_batch(trigger: str, items: list[TriggeredAction]) -> None:
81
90
  """Process a batch of queued action execution requests for a single trigger.
82
91
 
83
92
  Groups items by user and issues a single coalesced
@@ -90,26 +99,23 @@ def process_action_batch(trigger: str, items: list[dict]) -> None:
90
99
  if not items:
91
100
  return
92
101
 
93
- groups: dict[str | None, tuple[list[str], Any]] = {}
102
+ groups: dict[str | None, list[str]] = defaultdict(list)
94
103
 
95
104
  for item in items:
96
- user_data = item.get("user")
97
- user_key = user_data["uname"] if isinstance(user_data, dict) and "uname" in user_data else None
98
-
99
- if user_key not in groups:
100
- groups[user_key] = ([], user_data)
105
+ uname = item.get("uname")
101
106
 
102
- groups[user_key][0].extend(item["hit_ids"])
107
+ groups[uname].extend(item["hit_ids"])
103
108
 
104
- for user_key, (hit_ids, user_data) in groups.items():
109
+ for uname, hit_ids in groups.items():
105
110
  # Deduplicate IDs within a batch group
106
111
  unique_ids = list(dict.fromkeys(hit_ids))
107
112
  query = f"howler.id:({' OR '.join(sanitize_lucene_query(h) for h in unique_ids)})"
108
113
 
109
114
  try:
110
- bulk_execute_on_query(query, trigger=trigger, user=user_data)
115
+ user = datastore().user.get(uname)
116
+ bulk_execute_on_query(query, trigger=trigger, user=user)
111
117
  except Exception:
112
- logger.exception("Error processing action batch for trigger=%s user=%s", trigger, user_key)
118
+ logger.exception("Error processing action batch for trigger=%s user=%s", trigger, uname)
113
119
 
114
120
 
115
121
  def validate_action(new_action: Any) -> Optional[Response]: # noqa: C901
@@ -10,7 +10,7 @@ from howler.common.logging import get_logger
10
10
  from howler.datastore.collection import parse_sort
11
11
  from howler.datastore.exceptions import SearchException, SearchRetryException
12
12
  from howler.datastore.types import SearchResult
13
- from howler.helper.search import get_collection, has_access_control
13
+ from howler.helper.search import get_collection, get_default_sort, has_access_control
14
14
  from howler.odm.models.user import User
15
15
  from howler.services import case_service
16
16
  from howler.utils.indexes import get_logical_index_name, normalize_indexes
@@ -20,10 +20,15 @@ DEFAULT_ROW_SIZE = 25
20
20
  DEFAULT_SORT: list[dict[str, str]] = [{"_id": "asc"}]
21
21
  DEFAULT_SEARCH_FIELD = "__text__"
22
22
  SCROLL_TIMEOUT = "5m"
23
+ SENSITIVE_USER_FIELDS = ["password", "apikeys", "*"]
23
24
 
24
25
  logger = get_logger(__file__)
25
26
 
26
27
 
28
+ class SensitiveUserFieldsException(SearchException):
29
+ """Raised when a user search requests protected source fields."""
30
+
31
+
27
32
  def _format_items(hits: list[dict[str, Any]], user_classification: str | None) -> list[dict[str, Any]]:
28
33
  """Formats Elasticsearch search hits into a standardized item format.
29
34
 
@@ -93,6 +98,14 @@ def search( # noqa: C901
93
98
  """
94
99
  del metadata
95
100
 
101
+ index_list = _parse_index_list(indexes)
102
+ if (
103
+ fl is not None
104
+ and "user" in index_list
105
+ and any(sensitive_field in fl for sensitive_field in SENSITIVE_USER_FIELDS)
106
+ ):
107
+ raise SensitiveUserFieldsException("Invalid fields to retrieve.")
108
+
96
109
  client: Elasticsearch = datastore().ds.client
97
110
  parsed_indexes = normalize_indexes(indexes)
98
111
 
@@ -113,7 +126,12 @@ def search( # noqa: C901
113
126
  query = "id:*"
114
127
 
115
128
  if sort is None:
116
- sort = DEFAULT_SORT
129
+ default_sorts = [get_default_sort(index, user) for index in _parse_index_list(indexes)] if user else []
130
+ default_sort = default_sorts[0] if default_sorts else None
131
+ if default_sort is not None and all(index_sort == default_sort for index_sort in default_sorts):
132
+ sort = default_sort
133
+ else:
134
+ sort = DEFAULT_SORT
117
135
 
118
136
  if rows is None:
119
137
  rows = DEFAULT_ROW_SIZE
@@ -152,7 +152,7 @@ suppress-none-returning = true
152
152
  [tool.poetry]
153
153
  package-mode = true
154
154
  name = "howler-api"
155
- version = "4.1.0.dev1436"
155
+ version = "4.1.0.dev1460"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",