howler-api 3.3.0.dev713__tar.gz → 3.3.0.dev715__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 (199) hide show
  1. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/PKG-INFO +1 -1
  2. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/auth.py +4 -4
  3. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/clue.py +1 -1
  4. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/hit.py +2 -2
  5. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/tool.py +3 -3
  6. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/app.py +1 -1
  7. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/loader.py +2 -2
  8. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/cronjobs/retention.py +1 -1
  9. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/cronjobs/rules.py +12 -7
  10. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/cronjobs/view_cleanup.py +1 -1
  11. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/collection.py +32 -23
  12. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/migrations/fix_process.py +3 -3
  13. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/discover.py +3 -3
  14. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/helper.py +1 -1
  15. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/random_data.py +6 -6
  16. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/__init__.py +1 -1
  17. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/security/__init__.py +4 -4
  18. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/security/socket.py +4 -4
  19. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/event_service.py +3 -3
  20. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/pyproject.toml +1 -1
  21. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/README.md +0 -0
  22. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/__init__.py +0 -0
  23. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/__init__.py +0 -0
  24. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/add_label.py +0 -0
  25. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/add_to_bundle.py +0 -0
  26. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/change_field.py +0 -0
  27. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/demote.py +0 -0
  28. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/example_plugin.py +0 -0
  29. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/prioritization.py +0 -0
  30. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/promote.py +0 -0
  31. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/remove_from_bundle.py +0 -0
  32. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/remove_label.py +0 -0
  33. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/actions/transition.py +0 -0
  34. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/__init__.py +0 -0
  35. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/base.py +0 -0
  36. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/socket.py +0 -0
  37. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/__init__.py +0 -0
  38. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/action.py +0 -0
  39. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/analytic.py +0 -0
  40. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/configs.py +0 -0
  41. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/dossier.py +0 -0
  42. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/help.py +0 -0
  43. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/notebook.py +0 -0
  44. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/overview.py +0 -0
  45. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/search.py +0 -0
  46. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/template.py +0 -0
  47. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/user.py +0 -0
  48. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/utils/__init__.py +0 -0
  49. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/utils/etag.py +0 -0
  50. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/api/v1/view.py +0 -0
  51. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/README.md +0 -0
  52. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/__init__.py +0 -0
  53. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/classification.py +0 -0
  54. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/classification.yml +0 -0
  55. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/exceptions.py +0 -0
  56. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/logging/__init__.py +0 -0
  57. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/logging/audit.py +0 -0
  58. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/logging/format.py +0 -0
  59. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/net.py +0 -0
  60. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/net_static.py +0 -0
  61. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/random_user.py +0 -0
  62. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/common/swagger.py +0 -0
  63. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/config.py +0 -0
  64. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/cronjobs/__init__.py +0 -0
  65. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/README.md +0 -0
  66. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/__init__.py +0 -0
  67. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/bulk.py +0 -0
  68. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/constants.py +0 -0
  69. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/exceptions.py +0 -0
  70. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/howler_store.py +0 -0
  71. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/operations.py +0 -0
  72. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/schemas.py +0 -0
  73. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/store.py +0 -0
  74. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/support/__init__.py +0 -0
  75. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/support/build.py +0 -0
  76. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/support/schemas.py +0 -0
  77. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/datastore/types.py +0 -0
  78. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/error.py +0 -0
  79. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/README.md +0 -0
  80. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/__init__.py +0 -0
  81. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/generate_mitre.py +0 -0
  82. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/generate_sigma_rules.py +0 -0
  83. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/generate_tlds.py +0 -0
  84. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/reindex_data.py +0 -0
  85. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/external/wipe_databases.py +0 -0
  86. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/gunicorn_config.py +0 -0
  87. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/healthz.py +0 -0
  88. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/__init__.py +0 -0
  89. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/azure.py +0 -0
  90. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/hit.py +0 -0
  91. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/oauth.py +0 -0
  92. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/search.py +0 -0
  93. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/workflow.py +0 -0
  94. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/helper/ws.py +0 -0
  95. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/README.md +0 -0
  96. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/__init__.py +0 -0
  97. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/base.py +0 -0
  98. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/charter.txt +0 -0
  99. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/howler_enum.py +0 -0
  100. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/__init__.py +0 -0
  101. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/action.py +0 -0
  102. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/analytic.py +0 -0
  103. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/assemblyline.py +0 -0
  104. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/aws.py +0 -0
  105. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/azure.py +0 -0
  106. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/cbs.py +0 -0
  107. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/clue.py +0 -0
  108. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/config.py +0 -0
  109. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/dossier.py +0 -0
  110. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/__init__.py +0 -0
  111. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/agent.py +0 -0
  112. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/autonomous_system.py +0 -0
  113. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/client.py +0 -0
  114. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/cloud.py +0 -0
  115. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/code_signature.py +0 -0
  116. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/container.py +0 -0
  117. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/dns.py +0 -0
  118. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/egress.py +0 -0
  119. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/elf.py +0 -0
  120. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/email.py +0 -0
  121. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/error.py +0 -0
  122. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/event.py +0 -0
  123. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/faas.py +0 -0
  124. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/file.py +0 -0
  125. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/geo.py +0 -0
  126. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/group.py +0 -0
  127. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/hash.py +0 -0
  128. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/host.py +0 -0
  129. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/http.py +0 -0
  130. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/ingress.py +0 -0
  131. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/interface.py +0 -0
  132. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/network.py +0 -0
  133. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/observer.py +0 -0
  134. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/organization.py +0 -0
  135. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/os.py +0 -0
  136. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/pe.py +0 -0
  137. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/process.py +0 -0
  138. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/registry.py +0 -0
  139. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/related.py +0 -0
  140. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/rule.py +0 -0
  141. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/server.py +0 -0
  142. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/threat.py +0 -0
  143. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/tls.py +0 -0
  144. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/url.py +0 -0
  145. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/user.py +0 -0
  146. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/user_agent.py +0 -0
  147. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/ecs/vulnerability.py +0 -0
  148. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/gcp.py +0 -0
  149. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/hit.py +0 -0
  150. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/howler_data.py +0 -0
  151. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/lead.py +0 -0
  152. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/localized_label.py +0 -0
  153. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/overview.py +0 -0
  154. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/pivot.py +0 -0
  155. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/template.py +0 -0
  156. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/user.py +0 -0
  157. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/models/view.py +0 -0
  158. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/odm/randomizer.py +0 -0
  159. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/patched.py +0 -0
  160. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/plugins/__init__.py +0 -0
  161. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/plugins/config.py +0 -0
  162. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/__init__.py +0 -0
  163. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/README.md +0 -0
  164. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/counters.py +0 -0
  165. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/events.py +0 -0
  166. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/hash.py +0 -0
  167. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/lock.py +0 -0
  168. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/queues/__init__.py +0 -0
  169. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/queues/comms.py +0 -0
  170. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/queues/multi.py +0 -0
  171. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/queues/named.py +0 -0
  172. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/queues/priority.py +0 -0
  173. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/set.py +0 -0
  174. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  175. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/security/utils.py +0 -0
  176. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/__init__.py +0 -0
  177. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/action_service.py +0 -0
  178. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/analytic_service.py +0 -0
  179. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/auth_service.py +0 -0
  180. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/config_service.py +0 -0
  181. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/dossier_service.py +0 -0
  182. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/hit_service.py +0 -0
  183. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/jwt_service.py +0 -0
  184. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/lucene_service.py +0 -0
  185. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/notebook_service.py +0 -0
  186. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/overview_service.py +0 -0
  187. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/template_service.py +0 -0
  188. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/services/user_service.py +0 -0
  189. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/__init__.py +0 -0
  190. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/annotations.py +0 -0
  191. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/chunk.py +0 -0
  192. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/dict_utils.py +0 -0
  193. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/isotime.py +0 -0
  194. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/list_utils.py +0 -0
  195. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/lucene.py +0 -0
  196. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/path.py +0 -0
  197. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/socket_utils.py +0 -0
  198. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/str_utils.py +0 -0
  199. {howler_api-3.3.0.dev713 → howler_api-3.3.0.dev715}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 3.3.0.dev713
3
+ Version: 3.3.0.dev715
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -347,23 +347,23 @@ def login(**_): # noqa: C901
347
347
  # For sanity's sake, we throw exceptions throughout the authentication code and simply catch the exceptions here to
348
348
  # return the corresponding HTTP Code to the user
349
349
  except (OAuthError, AuthenticationException) as err:
350
- logger.warning(f"Authentication failure. (U:{user} - IP:{ip}) [{err}]")
350
+ logger.warning("Authentication failure. (U:%s - IP:%s) [%s]", user, ip, err)
351
351
  return unauthorized(err=str(err))
352
352
 
353
353
  except AccessDeniedException as err:
354
- logger.warning(f"Authorization failure. (U:{user} - IP:{ip}) [{err}]")
354
+ logger.warning("Authorization failure. (U:%s - IP:%s) [%s]", user, ip, err)
355
355
  return forbidden(err=err.message)
356
356
 
357
357
  except InvalidDataException as err:
358
358
  return bad_request(err=err.message or str(err))
359
359
 
360
360
  except HowlerException:
361
- logger.exception(f"Internal Authentication Error. (U:{user} - IP:{ip})")
361
+ logger.exception("Internal Authentication Error. (U:%s - IP:%s)", user, ip)
362
362
  return internal_error(
363
363
  err="Unhandled exception occured while Authenticating. Contact your administrator.",
364
364
  )
365
365
 
366
- logger.info(f"Login successful. (U:{logged_in_uname} - IP:{ip})")
366
+ logger.info("Login successful. (U:%s - IP:%s)", logged_in_uname, ip)
367
367
 
368
368
  xsrf_token = generate_random_secret()
369
369
 
@@ -91,7 +91,7 @@ def proxy_to_clue(path, **kwargs):
91
91
  timeout=5 * 60,
92
92
  )
93
93
 
94
- logger.debug(f"Request to clue completed in {round(time.perf_counter() - start)}ms")
94
+ logger.debug("Request to clue completed in %s ms", round(time.perf_counter() - start))
95
95
 
96
96
  if not response.ok:
97
97
  return bad_gateway(response.json(), err="Something went wrong when connecting to clue")
@@ -99,7 +99,7 @@ def create_hits(user: User, **kwargs):
99
99
  response_body: dict[str, list[Any]] = {"valid": [], "invalid": []}
100
100
  odms = []
101
101
  ignore_extra_values: bool = bool(request.args.get("ignore_extra_values", False, type=lambda v: v.lower() == "true"))
102
- logger.debug(f"ignore_extra_values = {ignore_extra_values}")
102
+ logger.debug("ignore_extra_values = %s", ignore_extra_values)
103
103
  warnings = []
104
104
  for hit in hits:
105
105
  try:
@@ -108,7 +108,7 @@ def create_hits(user: User, **kwargs):
108
108
  odms.append(odm)
109
109
  warnings.extend(_warnings)
110
110
  except HowlerException as e:
111
- logger.warning(f"{type(e).__name__} when saving new hit!")
111
+ logger.warning("%s when saving new hit!", type(e).__name__)
112
112
  logger.warning(e)
113
113
  response_body["invalid"].append({"input": hit, "error": str(e)})
114
114
 
@@ -67,7 +67,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
67
67
  field_map = data.pop("map", None)
68
68
  hits = data.pop("hits", None)
69
69
  ignore_extra_values: bool = bool(request.args.get("ignore_extra_values", False, type=lambda v: v.lower() == "true"))
70
- logger.debug(f"ignore_extra_values = {ignore_extra_values}")
70
+ logger.debug("ignore_extra_values = %s", ignore_extra_values)
71
71
  # Check data type
72
72
  if not isinstance(field_map, dict):
73
73
  return bad_request(err="Invalid: 'map' field is missing or invalid.")
@@ -115,7 +115,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
115
115
  try:
116
116
  field_data: Optional[_Field] = hit_fields[target]
117
117
  except KeyError:
118
- logger.debug(f"`{target}` not in hit fields")
118
+ logger.debug("`%s` not in hit fields", target)
119
119
  field_data = next(
120
120
  (v for k, v in hit_fields.items() if get_parent_key(k) == target),
121
121
  None,
@@ -153,7 +153,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
153
153
  }
154
154
  )
155
155
  except HowlerException as e:
156
- logger.warning(f"{type(e).__name__} when saving {cur_id}!")
156
+ logger.warning("%s when saving %s!", type(e).__name__, cur_id)
157
157
  logger.warning(e)
158
158
 
159
159
  out.append({"id": None, "error": str(e)})
@@ -206,7 +206,7 @@ if logger.parent:
206
206
 
207
207
  # Setup APMs
208
208
  if config.core.metrics.apm_server.server_url is not None:
209
- logger.info(f"Exporting application metrics to: {config.core.metrics.apm_server.server_url}")
209
+ logger.info("Exporting application metrics to: %s", config.core.metrics.apm_server.server_url)
210
210
  ElasticAPM(
211
211
  app,
212
212
  server_url=config.core.metrics.apm_server.server_url,
@@ -58,9 +58,9 @@ def get_classification(yml_config: Optional[str] = None): # noqa: C901
58
58
  )
59
59
 
60
60
  if not yml_config_path.exists():
61
- log.warning(f"{yml_config_path} does not exist!")
61
+ log.warning("%s does not exist!", yml_config_path)
62
62
  yml_config_path = Path("/etc") / APP_NAME.replace("-dev", "") / "classification.yml"
63
- log.warning(f"Checking at {yml_config_path} instead.")
63
+ log.warning("Checking at %s instead.", yml_config_path)
64
64
  else:
65
65
  yml_config_path = Path(yml_config)
66
66
 
@@ -39,7 +39,7 @@ def setup_job(sched: BaseScheduler):
39
39
 
40
40
  return
41
41
 
42
- logger.debug(f"Initializing retention cronjob with cron {config.system.retention.crontab}")
42
+ logger.debug("Initializing retention cronjob with cron %s", config.system.retention.crontab)
43
43
 
44
44
  if DEBUG:
45
45
  _kwargs: dict[str, Any] = {"next_run_time": datetime.now()}
@@ -44,7 +44,7 @@ def create_correlated_bundle(rule: Analytic, query: str, correlated_hits: list[H
44
44
  # If a matching bundle exists already, just reused it (likely only ever lucene specific)
45
45
  existing_result = datastore().hit.search(f"howler.hash:{hashed}", rows=1)
46
46
  if existing_result["total"] > 0:
47
- logger.debug(f"Rule hash {hashed} exists - skipping create")
47
+ logger.debug("Rule hash %s exists - skipping create", hashed)
48
48
  return existing_result["items"][0]
49
49
 
50
50
  child_ids = [match.howler.id for match in correlated_hits]
@@ -200,7 +200,10 @@ def create_executor(rule: Analytic): # noqa: C901
200
200
  __scheduler_instance.remove_job(f"rule_{rule.analytic_id}")
201
201
  # TODO: Allow restarting of rules
202
202
  logger.critical(
203
- f"Rule {rule.name} ({rule.analytic_id}) has been stopped, due to an exception: {type(e)}",
203
+ "Rule %s (%s) has been stopped, due to an exception: %s",
204
+ rule.name,
205
+ rule.analytic_id,
206
+ type(e),
204
207
  exc_info=True,
205
208
  )
206
209
 
@@ -220,12 +223,12 @@ def register_rules(new_rule: Optional[Analytic] = None, test_override: bool = Fa
220
223
 
221
224
  if new_rule:
222
225
  if __scheduler_instance.get_job(f"rule_{new_rule.analytic_id}"):
223
- logger.info(f"Updating existing rule: {new_rule.analytic_id} on interval {new_rule.rule_crontab}")
226
+ logger.info("Updating existing rule: %s on interval %s", new_rule.analytic_id, new_rule.rule_crontab)
224
227
 
225
228
  # remove the existing job
226
229
  __scheduler_instance.remove_job(f"rule_{new_rule.analytic_id}")
227
230
  else:
228
- logger.info(f"Registering new rule: {new_rule.analytic_id} on interval {new_rule.rule_crontab}")
231
+ logger.info("Registering new rule: %s on interval %s", new_rule.analytic_id, new_rule.rule_crontab)
229
232
  rules = [new_rule]
230
233
  else:
231
234
  logger.debug("Registering rules")
@@ -237,10 +240,12 @@ def register_rules(new_rule: Optional[Analytic] = None, test_override: bool = Fa
237
240
  interval = rule.rule_crontab or f"{random.randint(0, 59)} * * * *" # noqa: S311
238
241
 
239
242
  if __scheduler_instance.get_job(job_id):
240
- logger.debug(f"Rule {job_id} already running!")
243
+ logger.debug("Rule %s already running!", job_id)
241
244
  return
242
245
 
243
- logger.debug(f"Initializing rule cronjob with:\tJob ID: {job_id}\tRule Name: {rule.name}\tCrontab: {interval}")
246
+ logger.debug(
247
+ "Initializing rule cronjob with:\tJob ID: %s\tRule Name: %s\tCrontab: %s", job_id, rule.name, interval
248
+ )
244
249
 
245
250
  if DEBUG or new_rule:
246
251
  _kwargs: dict[str, Any] = {"next_run_time": datetime.now()}
@@ -255,7 +260,7 @@ def register_rules(new_rule: Optional[Analytic] = None, test_override: bool = Fa
255
260
  **_kwargs,
256
261
  )
257
262
 
258
- logger.info(f"Initialized {total_initialized} rules")
263
+ logger.info("Initialized %s rules", total_initialized)
259
264
 
260
265
 
261
266
  def setup_job(sched: BaseScheduler):
@@ -68,7 +68,7 @@ def setup_job(sched: BaseScheduler):
68
68
 
69
69
  return
70
70
 
71
- logger.debug(f"Initializing view cleanup cronjob with cron {config.system.view_cleanup.crontab}")
71
+ logger.debug("Initializing view cleanup cronjob with cron %s", config.system.view_cleanup.crontab)
72
72
 
73
73
  if DEBUG:
74
74
  _kwargs: dict[str, Any] = {"next_run_time": datetime.now()}
@@ -398,7 +398,7 @@ class ESCollection(Generic[ModelType]):
398
398
  except elasticsearch.exceptions.TransportError as e:
399
399
  err_code, msg, cause = e.args
400
400
  if err_code == 503 or err_code == "503":
401
- logger.warning(f"Looks like index {self.name} is not ready yet, retrying...")
401
+ logger.warning("Looks like index %s is not ready yet, retrying...", self.name)
402
402
  time.sleep(min(retries, self.MAX_RETRY_BACKOFF))
403
403
  self.datastore.connection_reset()
404
404
  retries += 1
@@ -411,7 +411,8 @@ class ESCollection(Generic[ModelType]):
411
411
  retries += 1
412
412
  elif err_code == 403 or err_code == "403":
413
413
  logger.warning(
414
- f"Elasticsearch cluster is preventing writing operations on index {self.name}, retrying..."
414
+ "Elasticsearch cluster is preventing writing operations on index %s, retrying...",
415
+ self.name,
415
416
  )
416
417
  time.sleep(min(retries, self.MAX_RETRY_BACKOFF))
417
418
  self.datastore.connection_reset()
@@ -470,7 +471,7 @@ class ESCollection(Generic[ModelType]):
470
471
  except elasticsearch.exceptions.TransportError as e:
471
472
  err_code, _, _ = e.args
472
473
  if err_code == 408 or err_code == "408":
473
- logger.warning(f"Waiting for index {index} to get to status {min_status}...")
474
+ logger.warning("Waiting for index %s to get to status %s...", index, min_status)
474
475
  else:
475
476
  raise
476
477
 
@@ -576,8 +577,9 @@ class ESCollection(Generic[ModelType]):
576
577
 
577
578
  if cur_shards > target_shards:
578
579
  logger.info(
579
- f"Current shards ({cur_shards}) is bigger then target shards ({target_shards}), "
580
- "we will be shrinking the index."
580
+ "Current shards (%s) is bigger then target shards (%s), we will be shrinking the index.",
581
+ cur_shards,
582
+ target_shards,
581
583
  )
582
584
  if cur_shards % target_shards != 0:
583
585
  logger.info("The target shards is not a factor of the current shards, aborting...")
@@ -591,8 +593,9 @@ class ESCollection(Generic[ModelType]):
591
593
  method = self.datastore.client.indices.shrink
592
594
  elif cur_shards < target_shards:
593
595
  logger.info(
594
- f"Current shards ({cur_shards}) is smaller then target shards ({target_shards}), "
595
- "we will be splitting the index."
596
+ "Current shards (%s) is smaller then target shards (%s), we will be splitting the index.",
597
+ cur_shards,
598
+ target_shards,
596
599
  )
597
600
  if target_shards % cur_shards != 0:
598
601
  logger.warning("The current shards is not a factor of the target shards, aborting...")
@@ -601,13 +604,15 @@ class ESCollection(Generic[ModelType]):
601
604
  method = self.datastore.client.indices.split
602
605
  else:
603
606
  logger.info(
604
- f"Current shards ({cur_shards}) is equal to the target shards ({target_shards}), "
605
- "only house keeping operations will be performed."
607
+ "Current shards (%s) is equal to the target shards (%s), only housekeeping operations will be "
608
+ "performed.",
609
+ cur_shards,
610
+ target_shards,
606
611
  )
607
612
 
608
613
  if method:
609
614
  # Before we do anything, we should make sure the source index is in a good state
610
- logger.info(f"Waiting for {self.name.upper()} status to be GREEN.")
615
+ logger.info("Waiting for %s status to be GREEN.", self.name.upper())
611
616
  self._wait_for_status(self.name, min_status="green")
612
617
 
613
618
  # Block all indexes to be written to
@@ -618,7 +623,7 @@ class ESCollection(Generic[ModelType]):
618
623
  if not self.with_retries(self.datastore.client.indices.exists, index=temp_name):
619
624
  # if there are specific settings to be applied to the index, apply them
620
625
  if clone_setup_settings:
621
- logger.info(f"Rellocating index to node {target_node.upper()}.")
626
+ logger.info("Relocating index to node %s.", target_node.upper())
622
627
  self.with_retries(
623
628
  self.datastore.client.indices.put_settings,
624
629
  index=self.index_name,
@@ -630,7 +635,7 @@ class ESCollection(Generic[ModelType]):
630
635
  time.sleep(1)
631
636
 
632
637
  # Make a clone of the current index
633
- logger.info(f"Cloning {self.index_name.upper()} into {temp_name.upper()}.")
638
+ logger.info("Cloning %s into %s.", self.index_name.upper(), temp_name.upper())
634
639
  self._safe_index_copy(
635
640
  self.datastore.client.indices.clone,
636
641
  self.index_name,
@@ -640,14 +645,16 @@ class ESCollection(Generic[ModelType]):
640
645
  )
641
646
 
642
647
  # Make 100% sure temporary index is ready
643
- logger.info(f"Waiting for {temp_name.upper()} status to be GREEN.")
648
+ logger.info("Waiting for %s status to be GREEN.", temp_name.upper())
644
649
  self._wait_for_status(temp_name, "green")
645
650
 
646
651
  # Make sure temporary index is the alias if not already
647
652
  if self._get_current_alias(self.name) != temp_name:
648
653
  logger.info(
649
- f"Make {temp_name.upper()} the current alias for {self.name.upper()} "
650
- f"and delete {self.index_name.upper()}."
654
+ "Make %s the current alias for %s and delete %s.",
655
+ temp_name.upper(),
656
+ self.name.upper(),
657
+ self.index_name.upper(),
651
658
  )
652
659
  # Make the hot index the temporary index while deleting the original index
653
660
  alias_actions = [
@@ -658,17 +665,19 @@ class ESCollection(Generic[ModelType]):
658
665
 
659
666
  # Make sure the original index is deleted
660
667
  if self.with_retries(self.datastore.client.indices.exists, index=self.index_name):
661
- logger.info(f"Delete extra {self.index_name.upper()} index.")
668
+ logger.info("Delete extra %s index.", self.index_name.upper())
662
669
  self.with_retries(self.datastore.client.indices.delete, index=self.index_name)
663
670
 
664
671
  # Shrink/split the temporary index into the original index
665
- logger.info(f"Perform shard fix operation from {temp_name.upper()} to {self.index_name.upper()}.")
672
+ logger.info("Perform shard fix operation from %s to %s.", temp_name.upper(), self.index_name.upper())
666
673
  self._safe_index_copy(method, temp_name, self.index_name, settings=settings)
667
674
 
668
675
  # Make the original index the new alias
669
676
  logger.info(
670
- f"Make {self.index_name.upper()} the current alias for {self.name.upper()} "
671
- f"and delete {temp_name.upper()}."
677
+ "Make %s the current alias for %s and delete %s.",
678
+ self.index_name.upper(),
679
+ self.name.upper(),
680
+ temp_name.upper(),
672
681
  )
673
682
  alias_actions = [
674
683
  {"add": {"index": self.index_name, "alias": self.name}},
@@ -681,7 +690,7 @@ class ESCollection(Generic[ModelType]):
681
690
  self.with_retries(self.datastore.client.indices.put_settings, settings=write_unblock_settings)
682
691
 
683
692
  # Restore normal routing and replicas
684
- logger.debug(f"Restore original routing table for {self.name.upper()}.")
693
+ logger.debug("Restore original routing table for %s.", self.name.upper())
685
694
  self.with_retries(
686
695
  self.datastore.client.indices.put_settings,
687
696
  index=self.name,
@@ -849,7 +858,7 @@ class ESCollection(Generic[ModelType]):
849
858
  key_list.remove(row["_id"])
850
859
  add_to_output(row["_source"], row["_id"])
851
860
  except ValueError:
852
- logger.exception(f"MGet returned multiple documents for id: {row['_id']}")
861
+ logger.exception("MGet returned multiple documents for id: %s", row["_id"])
853
862
 
854
863
  if key_list and error_on_missing:
855
864
  raise MultiKeyError(key_list, out)
@@ -2359,7 +2368,7 @@ class ESCollection(Generic[ModelType]):
2359
2368
  """
2360
2369
  # Create HOT index
2361
2370
  if not self.with_retries(self.datastore.client.indices.exists, index=self.name):
2362
- logger.debug(f"Index {self.name.upper()} does not exists. Creating it now...")
2371
+ logger.debug("Index %s does not exist. Creating it now...", self.name.upper())
2363
2372
  try:
2364
2373
  self.with_retries(
2365
2374
  self.datastore.client.indices.create,
@@ -2370,7 +2379,7 @@ class ESCollection(Generic[ModelType]):
2370
2379
  except elasticsearch.exceptions.RequestError as e:
2371
2380
  if "resource_already_exists_exception" not in str(e):
2372
2381
  raise
2373
- logger.warning(f"Tried to create an index template that already exists: {self.name.upper()}")
2382
+ logger.warning("Tried to create an index template that already exists: %s", self.name.upper())
2374
2383
 
2375
2384
  self.with_retries(
2376
2385
  self.datastore.client.indices.put_alias,
@@ -15,12 +15,12 @@ def migrate():
15
15
  logger.info("Preconditions met, continuing.")
16
16
 
17
17
  db_size = collection.search("howler.id:*", track_total_hits=True, rows=0)["total"]
18
- logger.info(f"Database size pre-migration: {db_size}")
18
+ logger.info("Database size pre-migration: %s", db_size)
19
19
  else:
20
20
  logger.info("Preconditions not met, stopping")
21
21
  return
22
22
 
23
- logger.info(f"We will delete {result['total']} hits. Continue?")
23
+ logger.info("We will delete %s hits. Continue?", result["total"])
24
24
  prompt_result = input("y/[n]")
25
25
 
26
26
  if prompt_result.lower() != "y":
@@ -32,7 +32,7 @@ def migrate():
32
32
  collection.commit()
33
33
 
34
34
  db_size_after = collection.search("howler.id:*", track_total_hits=True, rows=0)["total"]
35
- logger.info(f"Database size post-migration: {db_size_after}")
35
+ logger.info("Database size post-migration: %s", db_size_after)
36
36
 
37
37
  logger.info("Migration complete")
38
38
 
@@ -47,11 +47,11 @@ def get_apps_list(discovery_url: Optional[str]) -> list[dict[str, str]]:
47
47
  )
48
48
 
49
49
  except Exception:
50
- logger.exception(f"Failed to parse get app: {str(app)}")
50
+ logger.exception("Failed to parse get app: %s", str(app))
51
51
  else:
52
- logger.warning(f"Invalid response from server for apps discovery: {discovery_url}")
52
+ logger.warning("Invalid response from server for apps discovery: %s", discovery_url)
53
53
  except Exception:
54
- logger.exception(f"Failed to get apps from discover URL: {discovery_url}")
54
+ logger.exception("Failed to get apps from discover URL: %s", discovery_url)
55
55
 
56
56
  DISCO_CACHE[discovery_url] = sorted(apps, key=lambda k: k["name"])
57
57
  return sorted(apps, key=lambda k: k["name"])
@@ -361,7 +361,7 @@ def create_users_with_username(ds: HowlerDatastore, usernames: list[str]):
361
361
  ds.user.save(username, user_data)
362
362
 
363
363
  if "pytest" not in sys.modules:
364
- logger.info(f"{username}:{username}")
364
+ logger.info("%s:%s", username, username)
365
365
 
366
366
  ds.user.commit()
367
367
  ds.user_avatar.commit()
@@ -137,7 +137,7 @@ def create_users(ds):
137
137
  ds.view.save(admin_view.view_id, admin_view)
138
138
 
139
139
  if "pytest" not in sys.modules:
140
- logger.info(f"\t{user_data.uname}:{admin_pass}")
140
+ logger.info("\t%s:%s", user_data.uname, admin_pass)
141
141
 
142
142
  user_hash = get_password_hash(user_pass)
143
143
 
@@ -184,7 +184,7 @@ def create_users(ds):
184
184
  ds.view.save(user_view.view_id, user_view)
185
185
 
186
186
  if "pytest" not in sys.modules:
187
- logger.info(f"\t{user_data.uname}:{user_pass}")
187
+ logger.info("\t%s:%s", user_data.uname, user_pass)
188
188
 
189
189
  huey_hash = get_password_hash(huey_pass)
190
190
 
@@ -231,7 +231,7 @@ def create_users(ds):
231
231
  ds.view.save(huey_view.view_id, huey_view)
232
232
 
233
233
  if "pytest" not in sys.modules:
234
- logger.info(f"\t{huey_data.uname}:{huey_pass}")
234
+ logger.info("\t%s:%s", huey_data.uname, huey_pass)
235
235
 
236
236
  shawnh_view = View(
237
237
  {
@@ -261,7 +261,7 @@ def create_users(ds):
261
261
  ds.view.save(shawnh_view.view_id, shawnh_view)
262
262
 
263
263
  if "pytest" not in sys.modules:
264
- logger.info(f"\t{shawn_data.uname}:{shawnh_pass}")
264
+ logger.info("\t%s:%s", shawn_data.uname, shawnh_pass)
265
265
 
266
266
  goose_view = View(
267
267
  {
@@ -291,7 +291,7 @@ def create_users(ds):
291
291
  ds.view.save(goose_view.view_id, goose_view)
292
292
 
293
293
  if "pytest" not in sys.modules:
294
- logger.info(f"\t{goose_data.uname}:{goose_pass}")
294
+ logger.info("\t%s:%s", goose_data.uname, goose_pass)
295
295
 
296
296
  ds.user.commit()
297
297
  ds.user_avatar.commit()
@@ -892,7 +892,7 @@ if __name__ == "__main__":
892
892
 
893
893
  for index, operations in INDEXES.items():
894
894
  if index in args:
895
- logger.info(f"Creating {index}...")
895
+ logger.info("Creating %s...", index)
896
896
 
897
897
  # Create functions
898
898
  for create_fn in operations[1]:
@@ -60,7 +60,7 @@ def retry_call(func, *args, **kw):
60
60
 
61
61
  return ret_val
62
62
  except (redis.ConnectionError, ConnectionResetError) as ce:
63
- log.warning(f"No connection to Redis, reconnecting... [{ce}]")
63
+ log.warning("No connection to Redis, reconnecting... [%s]", ce)
64
64
  time.sleep(2**exponent)
65
65
  exponent = exponent + 1 if exponent < maximum else exponent
66
66
 
@@ -186,7 +186,7 @@ class api_login(object): # noqa: D101, N801
186
186
 
187
187
  ip = request.headers.get("X-Forwarded-For", request.remote_addr)
188
188
  if "pytest" not in sys.modules:
189
- logger.info(f"Logged in as {user['uname']} from {ip} for path {request.path}")
189
+ logger.info("Logged in as %s from %s for path %s", user["uname"], ip, request.path)
190
190
 
191
191
  # If auditing is enabled, write this successful access to the audit logs
192
192
  if self.audit:
@@ -231,13 +231,13 @@ class api_login(object): # noqa: D101, N801
231
231
  quota = user.get("api_quota", 25)
232
232
  if not QUOTA_TRACKER.begin(user["uname"], quota):
233
233
  if config.ui.enforce_quota:
234
- logger.warning(f"{user['uname']} was prevented from using the api due to exceeded quota.")
234
+ logger.warning("%s was prevented from using the api due to exceeded quota.", user["uname"])
235
235
  FAILED_ATTEMPTS.labels("429").inc()
236
236
  return too_many_requests(err=f"You've exceeded your maximum quota of {quota}")
237
237
  else:
238
- logger.debug(f"Quota of {quota} exceeded for user {user['uname']}.")
238
+ logger.debug("Quota of %s exceeded for user %s.", quota, user["uname"])
239
239
  else:
240
- logger.debug(f"Quota not enforced for {user['uname']}")
240
+ logger.debug("Quota not enforced for %s", user["uname"])
241
241
 
242
242
  # Save user data in kwargs for future reference in the wrapped method
243
243
  kwargs["user"] = user
@@ -51,7 +51,7 @@ def websocket_auth(required_type: Optional[list[str]] = None, required_priv: Opt
51
51
  raise AuthenticationException() # noqa: TRY301
52
52
 
53
53
  if not set(required_priv) & set(privs):
54
- logger.warning(f"{ws_id}: Authentication header is invalid")
54
+ logger.warning("%s: Authentication header is invalid", ws_id)
55
55
  ws.close(
56
56
  1008,
57
57
  ws_response(
@@ -63,7 +63,7 @@ def websocket_auth(required_type: Optional[list[str]] = None, required_priv: Opt
63
63
  )
64
64
  return forbidden()
65
65
 
66
- logger.info(f"{ws_id} authenticated as {user['uname']}")
66
+ logger.info("%s authenticated as %s", ws_id, user["uname"])
67
67
  ws.send(
68
68
  ws_response(
69
69
  "info",
@@ -77,13 +77,13 @@ def websocket_auth(required_type: Optional[list[str]] = None, required_priv: Opt
77
77
 
78
78
  f(ws, *args, ws_id=ws_id, username=user["uname"], privs=privs, **kwargs)
79
79
  except ConnectionClosed:
80
- logger.info(f"{ws_id}: Client closed connection")
80
+ logger.info("%s: Client closed connection", ws_id)
81
81
  except (
82
82
  AuthenticationException,
83
83
  ValueError,
84
84
  InvalidTokenError,
85
85
  ):
86
- logger.warning(f"{ws_id}: Authentication header is invalid")
86
+ logger.warning("%s: Authentication header is invalid", ws_id)
87
87
  if ws:
88
88
  ws.close(
89
89
  1008,
@@ -54,7 +54,7 @@ def emit(event: str, data: Any):
54
54
  if event not in handlers:
55
55
  return
56
56
 
57
- logger.debug(f"event:{event} - emitting data")
57
+ logger.debug("event:%s - emitting data", event)
58
58
 
59
59
  for handler in handlers[event]:
60
60
  handler(data)
@@ -72,7 +72,7 @@ def on(event: str, handler: Callable):
72
72
 
73
73
  handlers[event].append(handler)
74
74
 
75
- logger.debug(f"event:{event} - added listener")
75
+ logger.debug("event:%s - added listener", event)
76
76
 
77
77
 
78
78
  def off(event: str, handler: Callable):
@@ -90,4 +90,4 @@ def off(event: str, handler: Callable):
90
90
 
91
91
  handlers[event] = [h for h in handlers[event] if h != handler]
92
92
 
93
- logger.debug(f"event:{event} - removed listener")
93
+ logger.debug("event:%s - removed listener", event)
@@ -152,7 +152,7 @@ suppress-none-returning = true
152
152
  [tool.poetry]
153
153
  package-mode = true
154
154
  name = "howler-api"
155
- version = "3.3.0.dev713"
155
+ version = "3.3.0.dev715"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",