howler-api 4.0.0.dev676__tar.gz → 4.0.0.dev679__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.
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/PKG-INFO +1 -1
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/base.py +22 -2
- howler_api-4.0.0.dev679/howler/odm/mixins.py +97 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/case.py +2 -1
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/hit.py +3 -1
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/observable.py +3 -1
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/pyproject.toml +1 -1
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/README.md +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/add_label.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/change_field.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/demote.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/example_plugin.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/prioritization.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/promote.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/remove_label.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/actions/transition.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/base.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/socket.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/action.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/analytic.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/auth.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/clue.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/configs.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/dossier.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/help.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/hit.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/notebook.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/overview.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/search.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/template.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/tool.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/user.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/utils/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/utils/etag.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v1/view.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v2/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v2/case.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v2/ingest.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/api/v2/search.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/app.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/README.md +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/classification.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/classification.yml +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/exceptions.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/loader.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/logging/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/logging/audit.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/logging/format.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/net.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/net_static.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/random_user.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/common/swagger.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/config.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/cronjobs/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/cronjobs/retention.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/cronjobs/view_cleanup.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/README.md +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/bulk.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/collection.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/constants.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/exceptions.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/howler_store.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/migrations/fix_process.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/operations.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/schemas.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/store.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/support/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/support/build.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/support/schemas.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/types.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/error.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/external/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/external/generate_mitre.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/external/generate_sigma_rules.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/external/generate_tlds.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/external/reindex_data.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/external/wipe_databases.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/gunicorn_config.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/healthz.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/azure.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/discover.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/hit.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/oauth.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/search.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/workflow.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/helper/ws.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/README.md +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/charter.txt +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/constants.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/helper.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/howler_enum.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/action.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/analytic.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/assemblyline.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/aws.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/azure.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/cbs.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/clue.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/config.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/dossier.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/agent.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/autonomous_system.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/client.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/cloud.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/code_signature.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/container.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/dns.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/egress.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/elf.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/email.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/error.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/event.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/faas.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/file.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/geo.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/group.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/hash.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/host.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/http.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/ingress.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/interface.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/network.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/observer.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/organization.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/os.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/pe.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/process.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/registry.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/related.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/rule.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/server.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/threat.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/tls.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/url.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/user.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/user_agent.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/vulnerability.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/gcp.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/howler_data.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/lead.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/localized_label.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/overview.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/pivot.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/record.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/template.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/user.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/view.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/random_data.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/randomizer.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/patched.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/plugins/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/plugins/config.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/README.md +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/counters.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/events.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/hash.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/lock.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/comms.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/multi.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/named.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/priority.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/set.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/user_quota_tracker.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/security/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/security/socket.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/security/utils.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/action_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/analytic_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/auth_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/case_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/config_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/docs_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/dossier_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/event_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/hit_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/jwt_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/lucene_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/notebook_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/observable_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/overview_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/search_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/template_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/services/user_service.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/__init__.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/annotations.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/chunk.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/compat.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/dict_utils.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/isotime.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/list_utils.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/lucene.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/path.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/socket_utils.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/str_utils.py +0 -0
- {howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/utils/uid.py +0 -0
|
@@ -1503,11 +1503,31 @@ def recursive_set_name(field, name, to_parent=False):
|
|
|
1503
1503
|
recursive_set_name(field.child_type, name, to_parent=True)
|
|
1504
1504
|
|
|
1505
1505
|
|
|
1506
|
-
def model(index=None, store=None, description=None):
|
|
1507
|
-
"""Decorator
|
|
1506
|
+
def model(index=None, store=None, description=None, id_field=None):
|
|
1507
|
+
"""Decorator that finalizes a Model subclass for use with the datastore.
|
|
1508
|
+
Assigns metadata to the class (description, id field), validates that all
|
|
1509
|
+
declared field names are legal, recursively sets each field's name, and
|
|
1510
|
+
applies default index/store settings to every field.
|
|
1511
|
+
If ``id_field`` is not provided, it defaults to ``<classname_lower>_id``.
|
|
1512
|
+
Args:
|
|
1513
|
+
index: Default index setting applied to all fields on the model.
|
|
1514
|
+
store: Default store setting applied to all fields on the model.
|
|
1515
|
+
description: Human-readable description of the model.
|
|
1516
|
+
id_field: Name of the field used as the primary key. Defaults to
|
|
1517
|
+
``<classname_lower>_id`` when not specified.
|
|
1518
|
+
Returns:
|
|
1519
|
+
A class decorator that configures and returns the decorated Model subclass.
|
|
1520
|
+
Raises:
|
|
1521
|
+
HowlerValueError: If any field name fails the ``FIELD_SANITIZER`` regex
|
|
1522
|
+
or appears in ``BANNED_FIELDS``.
|
|
1523
|
+
"""
|
|
1508
1524
|
|
|
1509
1525
|
def _finish_model(cls):
|
|
1510
1526
|
cls._Model__description = description
|
|
1527
|
+
cls._Model__id_field = id_field
|
|
1528
|
+
|
|
1529
|
+
if cls._Model__id_field is None:
|
|
1530
|
+
cls._Model__id_field = f"{cls.__name__.lower()}_id"
|
|
1511
1531
|
|
|
1512
1532
|
for name, field_data in cls.fields().items():
|
|
1513
1533
|
if not FIELD_SANITIZER.match(name) or name in BANNED_FIELDS:
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Datastore convenience mixins for Howler ODM Model classes.
|
|
2
|
+
|
|
3
|
+
Provides :class:`DatastoreMixin`, a generic mixin that adds a class-level
|
|
4
|
+
``store`` property (returning a typed :class:`ESCollection`) and instance-level
|
|
5
|
+
``ds`` / ``save`` helpers so that Model subclasses can interact with the
|
|
6
|
+
Elasticsearch datastore without boilerplate.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from operator import attrgetter
|
|
12
|
+
from typing import Generic, TypeVar, overload
|
|
13
|
+
|
|
14
|
+
from howler.common.exceptions import HowlerRuntimeError
|
|
15
|
+
from howler.common.loader import datastore
|
|
16
|
+
from howler.datastore.collection import ESCollection
|
|
17
|
+
from howler.odm.base import Model
|
|
18
|
+
|
|
19
|
+
ModelType = TypeVar("ModelType", bound=Model)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class _ObjectsDescriptor(Generic[ModelType]):
|
|
23
|
+
"""Descriptor that provides class-level-only access to the model's ESCollection.
|
|
24
|
+
|
|
25
|
+
Intended to be accessed exclusively via the class (e.g. ``Case.store``).
|
|
26
|
+
Raises ``AttributeError`` if accessed from an instance to enforce
|
|
27
|
+
cla # noqa: D205
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
@overload
|
|
31
|
+
def __get__(self, obj: None, objtype: type[ModelType]) -> ESCollection[ModelType]: ...
|
|
32
|
+
|
|
33
|
+
@overload
|
|
34
|
+
def __get__(self, obj: ModelType, objtype: type[ModelType]) -> ESCollection[ModelType]: ...
|
|
35
|
+
|
|
36
|
+
def __get__(self, obj: ModelType | None, objtype: type[ModelType] | None = None) -> ESCollection[ModelType]:
|
|
37
|
+
"""Return the ESCollection for the owner class.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
obj: The instance the descriptor was accessed from, or ``None``
|
|
41
|
+
when accessed via the class.
|
|
42
|
+
objtype: The owner class (e.g. ``Case``, ``Hit``).
|
|
43
|
+
Returns:
|
|
44
|
+
ESCollection[ModelType]: The datastore collection for *objtype*.
|
|
45
|
+
Raises:
|
|
46
|
+
AttributeError: If accessed from an instance (*obj* is not ``None``)
|
|
47
|
+
or if *objtype* cannot be determined.
|
|
48
|
+
"""
|
|
49
|
+
if obj is not None:
|
|
50
|
+
raise HowlerRuntimeError(
|
|
51
|
+
f"'{type(obj).__name__}.store' is a class-level property and cannot be accessed from an instance. "
|
|
52
|
+
f"Use '{type(obj).__name__}.store' instead."
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if objtype is None:
|
|
56
|
+
raise HowlerRuntimeError("Cannot resolve owner class for 'store' descriptor.")
|
|
57
|
+
|
|
58
|
+
index_name = objtype.__name__.lower()
|
|
59
|
+
return datastore()[index_name]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class DatastoreMixin(Generic[ModelType]):
|
|
63
|
+
"""Mixin that provides convenience datastore access to Model instances.
|
|
64
|
+
|
|
65
|
+
Generic over ``ModelType`` so that the ``store`` class property returns a
|
|
66
|
+
correctly-typed ``ESCollection[ModelType]``. Adds a ``ds`` property for
|
|
67
|
+
retrieving the shared datastore connection, a ``store`` class-only property
|
|
68
|
+
for retrieving the model's ESCollection (raises ``AttributeError`` if accessed
|
|
69
|
+
from an instance), and a ``save`` method that persists the current model
|
|
70
|
+
instance using its class name as the index and its configured ID field as the
|
|
71
|
+
document key.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
store: _ObjectsDescriptor = _ObjectsDescriptor()
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def ds(self):
|
|
78
|
+
"""Return the shared datastore instance.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
The singleton datastore connection used for all persistence operations.
|
|
82
|
+
"""
|
|
83
|
+
return datastore()
|
|
84
|
+
|
|
85
|
+
def save(self) -> bool:
|
|
86
|
+
"""Persist the current model instance to the datastore.
|
|
87
|
+
|
|
88
|
+
Determines the target index from the lowercase class name, extracts the
|
|
89
|
+
model's ID from the configured ID field, and saves the instance.
|
|
90
|
+
Returns:
|
|
91
|
+
bool: True if the save operation succeeded, False otherwise.
|
|
92
|
+
"""
|
|
93
|
+
index_name = self.__class__.__name__.lower()
|
|
94
|
+
id_field = self.__class__._Model__id_field # type: ignore[attr-defined]
|
|
95
|
+
current_id = attrgetter(id_field)(self)
|
|
96
|
+
|
|
97
|
+
return self.ds[index_name].save(current_id, self)
|
|
@@ -3,6 +3,7 @@ from typing import Any, Optional
|
|
|
3
3
|
from howler import odm
|
|
4
4
|
from howler.common.exceptions import HowlerValueError
|
|
5
5
|
from howler.odm.constants import Status
|
|
6
|
+
from howler.odm.mixins import DatastoreMixin
|
|
6
7
|
from howler.utils.compat import StrEnum
|
|
7
8
|
|
|
8
9
|
CASE_ITEM_TYPES = {"observable", "hit", "case", "lead", "reference"}
|
|
@@ -92,7 +93,7 @@ class CaseEnrichment(odm.Model):
|
|
|
92
93
|
|
|
93
94
|
|
|
94
95
|
@odm.model(index=True, store=True, description="Case model with path-based items, enrichments, rules, and tasks.")
|
|
95
|
-
class Case(odm.Model):
|
|
96
|
+
class Case(DatastoreMixin["Case"], odm.Model):
|
|
96
97
|
case_id: str = odm.UUID(description="A unique identifier for this case.")
|
|
97
98
|
title: str = odm.Keyword(description="Case title.")
|
|
98
99
|
summary: str = odm.Text(description="Short case summary.")
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from howler import odm
|
|
4
4
|
from howler.common.logging import get_logger
|
|
5
|
+
from howler.odm.mixins import DatastoreMixin
|
|
5
6
|
from howler.odm.models.howler_data import HowlerData
|
|
6
7
|
from howler.odm.models.record import Record
|
|
7
8
|
|
|
@@ -12,8 +13,9 @@ logger = get_logger(__file__)
|
|
|
12
13
|
index=True,
|
|
13
14
|
store=True,
|
|
14
15
|
description="Howler Outline schema which is an extended version of Elastic Common Schema (ECS)",
|
|
16
|
+
id_field="howler.id",
|
|
15
17
|
)
|
|
16
|
-
class Hit(Record):
|
|
18
|
+
class Hit(DatastoreMixin["Hit"], Record):
|
|
17
19
|
# Howler extended fields. Deviates from ECS
|
|
18
20
|
howler: HowlerData = odm.Compound(
|
|
19
21
|
HowlerData,
|
|
@@ -4,6 +4,7 @@ from howler import odm
|
|
|
4
4
|
from howler.common.exceptions import HowlerValueError
|
|
5
5
|
from howler.common.logging import get_logger
|
|
6
6
|
from howler.odm.howler_enum import HowlerEnum
|
|
7
|
+
from howler.odm.mixins import DatastoreMixin
|
|
7
8
|
from howler.odm.models.record import Record
|
|
8
9
|
|
|
9
10
|
logger = get_logger(__file__)
|
|
@@ -110,8 +111,9 @@ class ObservableData(odm.Model):
|
|
|
110
111
|
index=True,
|
|
111
112
|
store=True,
|
|
112
113
|
description="Observable schema which is an extended version of Elastic Common Schema (ECS)",
|
|
114
|
+
id_field="howler.id",
|
|
113
115
|
)
|
|
114
|
-
class Observable(Record):
|
|
116
|
+
class Observable(DatastoreMixin["Observable"], Record):
|
|
115
117
|
# Howler extended fields. Deviates from ECS
|
|
116
118
|
howler: ObservableData = odm.Compound(
|
|
117
119
|
ObservableData,
|
|
@@ -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.0.0.
|
|
155
|
+
version = "4.0.0.dev679"
|
|
156
156
|
description = "Howler - API server"
|
|
157
157
|
authors = [
|
|
158
158
|
"Canadian Centre for Cyber Security <howler@cyber.gc.ca>",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/datastore/migrations/fix_process.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/odm/models/ecs/autonomous_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/queues/priority.py
RENAMED
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev676 → howler_api-4.0.0.dev679}/howler/remote/datatypes/user_quota_tracker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|