howler-api 2.12.0.dev265__tar.gz → 2.12.0.dev278__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 (198) hide show
  1. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/PKG-INFO +1 -1
  2. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/analytic_service.py +12 -4
  3. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/hit_service.py +28 -24
  4. howler_api-2.12.0.dev278/howler/services/overview_service.py +44 -0
  5. howler_api-2.12.0.dev278/howler/services/template_service.py +45 -0
  6. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/pyproject.toml +1 -1
  7. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/README.md +0 -0
  8. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/__init__.py +0 -0
  9. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/__init__.py +0 -0
  10. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/add_label.py +0 -0
  11. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/add_to_bundle.py +0 -0
  12. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/change_field.py +0 -0
  13. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/demote.py +0 -0
  14. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/example_plugin.py +0 -0
  15. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/prioritization.py +0 -0
  16. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/promote.py +0 -0
  17. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/remove_from_bundle.py +0 -0
  18. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/remove_label.py +0 -0
  19. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/actions/transition.py +0 -0
  20. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/__init__.py +0 -0
  21. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/base.py +0 -0
  22. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/socket.py +0 -0
  23. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/__init__.py +0 -0
  24. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/action.py +0 -0
  25. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/analytic.py +0 -0
  26. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/auth.py +0 -0
  27. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/borealis.py +0 -0
  28. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/configs.py +0 -0
  29. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/dossier.py +0 -0
  30. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/help.py +0 -0
  31. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/hit.py +0 -0
  32. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/notebook.py +0 -0
  33. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/overview.py +0 -0
  34. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/search.py +0 -0
  35. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/template.py +0 -0
  36. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/tool.py +0 -0
  37. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/user.py +0 -0
  38. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/utils/__init__.py +0 -0
  39. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/utils/etag.py +0 -0
  40. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/api/v1/view.py +0 -0
  41. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/app.py +0 -0
  42. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/README.md +0 -0
  43. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/__init__.py +0 -0
  44. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/classification.py +0 -0
  45. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/classification.yml +0 -0
  46. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/exceptions.py +0 -0
  47. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/hexdump.py +0 -0
  48. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/iprange.py +0 -0
  49. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/loader.py +0 -0
  50. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/logging/__init__.py +0 -0
  51. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/logging/audit.py +0 -0
  52. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/logging/format.py +0 -0
  53. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/net.py +0 -0
  54. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/net_static.py +0 -0
  55. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/random_user.py +0 -0
  56. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/common/swagger.py +0 -0
  57. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/config.py +0 -0
  58. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/cronjobs/__init__.py +0 -0
  59. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/cronjobs/retention.py +0 -0
  60. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/cronjobs/rules.py +0 -0
  61. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/README.md +0 -0
  62. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/__init__.py +0 -0
  63. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/bulk.py +0 -0
  64. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/collection.py +0 -0
  65. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/constants.py +0 -0
  66. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/exceptions.py +0 -0
  67. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/howler_store.py +0 -0
  68. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/migrations/fix_process.py +0 -0
  69. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/operations.py +0 -0
  70. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/schemas.py +0 -0
  71. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/store.py +0 -0
  72. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/support/__init__.py +0 -0
  73. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/support/build.py +0 -0
  74. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/support/schemas.py +0 -0
  75. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/datastore/types.py +0 -0
  76. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/error.py +0 -0
  77. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/external/__init__.py +0 -0
  78. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/external/generate_mitre.py +0 -0
  79. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/external/generate_sigma_rules.py +0 -0
  80. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/external/generate_tlds.py +0 -0
  81. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/external/reindex_data.py +0 -0
  82. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/external/wipe_databases.py +0 -0
  83. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/gunicorn_config.py +0 -0
  84. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/healthz.py +0 -0
  85. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/__init__.py +0 -0
  86. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/azure.py +0 -0
  87. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/discover.py +0 -0
  88. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/hit.py +0 -0
  89. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/oauth.py +0 -0
  90. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/search.py +0 -0
  91. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/workflow.py +0 -0
  92. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/helper/ws.py +0 -0
  93. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/README.md +0 -0
  94. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/__init__.py +0 -0
  95. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/base.py +0 -0
  96. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/charter.txt +0 -0
  97. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/helper.py +0 -0
  98. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/howler_enum.py +0 -0
  99. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/__init__.py +0 -0
  100. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/action.py +0 -0
  101. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/analytic.py +0 -0
  102. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/assemblyline.py +0 -0
  103. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/aws.py +0 -0
  104. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/azure.py +0 -0
  105. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/cbs.py +0 -0
  106. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/config.py +0 -0
  107. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/dossier.py +0 -0
  108. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/__init__.py +0 -0
  109. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/agent.py +0 -0
  110. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/autonomous_system.py +0 -0
  111. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/client.py +0 -0
  112. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/cloud.py +0 -0
  113. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/code_signature.py +0 -0
  114. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/container.py +0 -0
  115. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/dns.py +0 -0
  116. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/egress.py +0 -0
  117. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/elf.py +0 -0
  118. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/email.py +0 -0
  119. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/error.py +0 -0
  120. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/event.py +0 -0
  121. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/faas.py +0 -0
  122. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/file.py +0 -0
  123. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/geo.py +0 -0
  124. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/group.py +0 -0
  125. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/hash.py +0 -0
  126. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/host.py +0 -0
  127. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/http.py +0 -0
  128. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/ingress.py +0 -0
  129. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/interface.py +0 -0
  130. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/network.py +0 -0
  131. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/observer.py +0 -0
  132. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/organization.py +0 -0
  133. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/os.py +0 -0
  134. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/pe.py +0 -0
  135. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/process.py +0 -0
  136. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/registry.py +0 -0
  137. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/related.py +0 -0
  138. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/rule.py +0 -0
  139. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/server.py +0 -0
  140. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/threat.py +0 -0
  141. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/tls.py +0 -0
  142. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/url.py +0 -0
  143. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/user.py +0 -0
  144. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/user_agent.py +0 -0
  145. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/ecs/vulnerability.py +0 -0
  146. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/gcp.py +0 -0
  147. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/hit.py +0 -0
  148. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/howler_data.py +0 -0
  149. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/lead.py +0 -0
  150. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/localized_label.py +0 -0
  151. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/overview.py +0 -0
  152. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/pivot.py +0 -0
  153. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/template.py +0 -0
  154. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/user.py +0 -0
  155. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/models/view.py +0 -0
  156. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/random_data.py +0 -0
  157. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/odm/randomizer.py +0 -0
  158. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/patched.py +0 -0
  159. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/plugins/__init__.py +0 -0
  160. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/plugins/config.py +0 -0
  161. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/__init__.py +0 -0
  162. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/README.md +0 -0
  163. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/__init__.py +0 -0
  164. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/counters.py +0 -0
  165. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/events.py +0 -0
  166. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/hash.py +0 -0
  167. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/lock.py +0 -0
  168. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/queues/__init__.py +0 -0
  169. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/queues/comms.py +0 -0
  170. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/queues/multi.py +0 -0
  171. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/queues/named.py +0 -0
  172. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/queues/priority.py +0 -0
  173. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/set.py +0 -0
  174. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  175. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/security/__init__.py +0 -0
  176. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/security/socket.py +0 -0
  177. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/security/utils.py +0 -0
  178. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/__init__.py +0 -0
  179. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/action_service.py +0 -0
  180. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/auth_service.py +0 -0
  181. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/config_service.py +0 -0
  182. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/dossier_service.py +0 -0
  183. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/event_service.py +0 -0
  184. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/jwt_service.py +0 -0
  185. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/lucene_service.py +0 -0
  186. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/notebook_service.py +0 -0
  187. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/services/user_service.py +0 -0
  188. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/__init__.py +0 -0
  189. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/annotations.py +0 -0
  190. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/chunk.py +0 -0
  191. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/dict_utils.py +0 -0
  192. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/isotime.py +0 -0
  193. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/list_utils.py +0 -0
  194. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/lucene.py +0 -0
  195. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/path.py +0 -0
  196. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/socket_utils.py +0 -0
  197. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/str_utils.py +0 -0
  198. {howler_api-2.12.0.dev265 → howler_api-2.12.0.dev278}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: howler-api
3
- Version: 2.12.0.dev265
3
+ Version: 2.12.0.dev278
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -2,6 +2,7 @@ from typing import Any, Union
2
2
 
3
3
  from howler.common.loader import datastore
4
4
  from howler.common.logging import get_logger
5
+ from howler.datastore.exceptions import SearchException
5
6
  from howler.datastore.operations import OdmUpdateOperation
6
7
  from howler.odm.models.analytic import Analytic
7
8
  from howler.odm.models.hit import Hit
@@ -46,17 +47,24 @@ def get_matching_analytics(hits: Union[list[Hit], list[dict[str, Any]]]) -> list
46
47
  Returns:
47
48
  list[Analytic]: A list of Analytic objects that match the analytics referenced in the hits.
48
49
  """
50
+ if len(hits) < 1:
51
+ return []
52
+
49
53
  storage = datastore()
50
54
 
51
55
  analytic_names: set[str] = set()
52
56
  for hit in hits:
53
57
  analytic_names.add(f'"{sanitize_lucene_query(hit["howler"]["analytic"])}"')
54
58
 
55
- existing_analytics: list[Analytic] = storage.analytic.search(f'name:({" OR ".join(analytic_names)})', as_obj=True)[
56
- "items"
57
- ]
59
+ try:
60
+ existing_analytics: list[Analytic] = storage.analytic.search(
61
+ f'name:({" OR ".join(analytic_names)})', as_obj=True
62
+ )["items"]
58
63
 
59
- return existing_analytics
64
+ return existing_analytics
65
+ except SearchException:
66
+ logger.exception("Exception on analytic matching")
67
+ return []
60
68
 
61
69
 
62
70
  def save_from_hit(hit: Hit, user: User):
@@ -30,11 +30,11 @@ from howler.odm.models.ecs.event import Event
30
30
  from howler.odm.models.hit import Hit
31
31
  from howler.odm.models.howler_data import HitOperationType, HitStatus, HitStatusTransition, Log
32
32
  from howler.odm.models.user import User
33
- from howler.services import action_service, analytic_service, dossier_service
33
+ from howler.services import action_service, analytic_service, dossier_service, overview_service, template_service
34
34
  from howler.utils.dict_utils import extra_keys, flatten
35
35
  from howler.utils.uid import get_random_id
36
36
 
37
- log = get_logger(__file__)
37
+ logger = get_logger(__file__)
38
38
 
39
39
  odm_helper = OdmHelper(Hit)
40
40
 
@@ -535,7 +535,7 @@ def _update_hit(
535
535
  else:
536
536
  operation_type = HitOperationType.SET
537
537
 
538
- log.debug("%s - %s - %s -> %s", hit_id, operation.key, previous_value, operation.value)
538
+ logger.debug("%s - %s - %s -> %s", hit_id, operation.key, previous_value, operation.value)
539
539
  final_operations.append(operation)
540
540
 
541
541
  if not operation.silent:
@@ -640,7 +640,7 @@ def transition_hit(
640
640
 
641
641
  # Log all hits that will be transitioned
642
642
  all_hit_ids = [h["howler"]["id"] for h in ([primary_hit] + [ch for ch in child_hits if ch])]
643
- log.debug("Transitioning (%s)", ", ".join(all_hit_ids))
643
+ logger.debug("Transitioning (%s)", ", ".join(all_hit_ids))
644
644
 
645
645
  # Process each hit (primary + children) with the workflow transition
646
646
  for current_hit in [primary_hit] + [ch for ch in child_hits if ch]:
@@ -650,7 +650,7 @@ def transition_hit(
650
650
  # Skip hits that don't match the primary hit's status
651
651
  # This ensures consistent state transitions across bundles
652
652
  if current_hit_status != primary_hit_status:
653
- log.debug("Skipping %s (status mismatch)", current_hit_id)
653
+ logger.debug("Skipping %s (status mismatch)", current_hit_id)
654
654
  continue
655
655
 
656
656
  # Apply the workflow transition to get required updates
@@ -837,33 +837,37 @@ def augment_metadata(data: list[dict[str, Any]] | dict[str, Any], metadata: list
837
837
  This function modifies the input data in-place, adding metadata fields.
838
838
  Templates are filtered based on user permissions (global or owned by user).
839
839
  """
840
- hits = data if isinstance(data, list) else [data]
840
+ if isinstance(data, list):
841
+ hits = data
842
+ elif data is not None:
843
+ hits = [data]
844
+ else:
845
+ hits = []
846
+
847
+ if len(hits) < 1:
848
+ return
849
+
850
+ logger.debug("Augmenting %s hits with %s", len(hits), ",".join(metadata))
841
851
 
842
- analytics: set[str] = set()
843
- for hit in hits:
844
- analytics.add(f'"{hit["howler"]["analytic"]}"')
852
+ if "template" in metadata:
853
+ template_candidates = template_service.get_matching_templates(hits, user["uname"], as_odm=False)
845
854
 
846
- if len(analytics) > 0:
847
- if "template" in metadata:
848
- template_candidates = datastore().template.search(
849
- f"analytic:({' OR '.join(analytics)}) AND (type:global OR owner:{user['uname']})",
850
- as_obj=False,
851
- )["items"]
855
+ logger.debug("\tRetrieved %s matching templates", len(template_candidates))
852
856
 
853
- for hit in hits:
854
- hit["__template"] = __match_metadata(template_candidates, hit)
857
+ for hit in hits:
858
+ hit["__template"] = __match_metadata(cast(list[dict[str, Any]], template_candidates), hit)
859
+
860
+ if "overview" in metadata:
861
+ overview_candidates = overview_service.get_matching_overviews(hits, as_odm=False)
855
862
 
856
- if "overview" in metadata:
857
- overview_candidates = datastore().overview.search(
858
- f"analytic:({' OR '.join(analytics)})",
859
- as_obj=False,
860
- )["items"]
863
+ logger.debug("\tRetrieved %s matching overviews", len(overview_candidates))
861
864
 
862
- for hit in hits:
863
- hit["__overview"] = __match_metadata(overview_candidates, hit)
865
+ for hit in hits:
866
+ hit["__overview"] = __match_metadata(cast(list[dict[str, Any]], overview_candidates), hit)
864
867
 
865
868
  if "analytic" in metadata:
866
869
  matched_analytics = analytic_service.get_matching_analytics(hits)
870
+ logger.debug("\tRetrieved %s matching analytics", len(matched_analytics))
867
871
 
868
872
  for hit in hits:
869
873
  matched_analytic = next(
@@ -0,0 +1,44 @@
1
+ from typing import Any, Union
2
+
3
+ from howler.common.loader import datastore
4
+ from howler.common.logging import get_logger
5
+ from howler.datastore.exceptions import SearchException
6
+ from howler.odm.models.hit import Hit
7
+ from howler.odm.models.overview import Overview
8
+ from howler.utils.str_utils import sanitize_lucene_query
9
+
10
+ logger = get_logger(__file__)
11
+
12
+
13
+ def get_matching_overviews(
14
+ hits: Union[list[Hit], list[dict[str, Any]]], as_odm: bool = False
15
+ ) -> Union[list[dict[str, Any]], list[Overview]]:
16
+ """Generate a list of overviews matching a given list of analytic names from the provided hits.
17
+
18
+ Args:
19
+ hits (list[Hit] | list[dict[str, Any]]): A list of Hit objects or dictionaries containing analytic information.
20
+ as_odm (bool, optional): If True, return Overview objects; otherwise, return dictionaries. Defaults to False.
21
+
22
+ Returns:
23
+ list[dict[str, Any]] | list[Overview]: A list of matching overviews, either as dictionaries or Overview objects.
24
+ """
25
+ if len(hits) < 1:
26
+ return []
27
+
28
+ analytic_names: set[str] = set()
29
+ for hit in hits:
30
+ analytic_names.add(f'"{sanitize_lucene_query(hit["howler"]["analytic"])}"')
31
+
32
+ if len(analytic_names) < 1:
33
+ return []
34
+
35
+ try:
36
+ overview_candidates = datastore().overview.search(
37
+ f"analytic:({' OR '.join(analytic_names)})",
38
+ as_obj=as_odm,
39
+ )["items"]
40
+
41
+ return overview_candidates
42
+ except SearchException:
43
+ logger.exception("Exception on analytic matching")
44
+ return []
@@ -0,0 +1,45 @@
1
+ from typing import Any, Optional, Union
2
+
3
+ from howler.common.loader import datastore
4
+ from howler.common.logging import get_logger
5
+ from howler.datastore.exceptions import SearchException
6
+ from howler.odm.models.analytic import Analytic
7
+ from howler.odm.models.hit import Hit
8
+ from howler.utils.str_utils import sanitize_lucene_query
9
+
10
+ logger = get_logger(__file__)
11
+
12
+
13
+ def get_matching_templates(
14
+ hits: Union[list[Hit], list[dict[str, Any]]], uname: Optional[str] = None, as_odm: bool = False
15
+ ) -> Union[list[dict[str, Any]], list[Analytic]]:
16
+ """Generate a list of templates matching a given list of analytic names, and optionally a user.
17
+
18
+ Args:
19
+ hits (list[Hit] | list[dict[str, Any]]]: List of hits, each containing analytic information.
20
+ uname (Optional[str], optional): Username to filter templates by owner. Defaults to None.
21
+ as_odm (bool, optional): If True, return results as ODM objects. If False, return as dicts. Defaults to False.
22
+
23
+ Returns:
24
+ list[dict[str, Any]] | list[Analytic]: List of matching templates, either as dicts or Analytic ODM objects.
25
+ """
26
+ if len(hits) < 1:
27
+ return []
28
+
29
+ analytic_names: set[str] = set()
30
+ for hit in hits:
31
+ analytic_names.add(f'"{sanitize_lucene_query(hit["howler"]["analytic"])}"')
32
+
33
+ if len(analytic_names) < 1:
34
+ return []
35
+
36
+ try:
37
+ template_candidates = datastore().template.search(
38
+ f"analytic:({' OR '.join(analytic_names)}) AND (type:global OR owner:{uname or '*'})",
39
+ as_obj=as_odm,
40
+ )["items"]
41
+
42
+ return template_candidates
43
+ except SearchException:
44
+ logger.exception("Exception on analytic matching")
45
+ return []
@@ -148,7 +148,7 @@ suppress-none-returning = true
148
148
  [tool.poetry]
149
149
  package-mode = true
150
150
  name = "howler-api"
151
- version = "2.12.0.dev265"
151
+ version = "2.12.0.dev278"
152
152
  description = "Howler - API server"
153
153
  authors = [
154
154
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",