mmisp-lib 0.9.0__tar.gz → 0.10.0__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.
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/PKG-INFO +9 -6
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/pyproject.toml +10 -6
- mmisp_lib-0.10.0/src/mmisp/api_schemas/attribute_common.py +48 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/attributes.py +134 -137
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/auth_keys.py +43 -37
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/authentication.py +2 -4
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/common.py +19 -5
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/events.py +143 -263
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/feeds.py +29 -34
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/galaxies.py +48 -81
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/galaxy_clusters.py +52 -36
- mmisp_lib-0.10.0/src/mmisp/api_schemas/galaxy_common.py +73 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/jobs.py +46 -52
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/noticelists.py +8 -12
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/object_templates.py +37 -22
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/objects.py +40 -30
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/organisations.py +24 -30
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/roles.py +34 -56
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/servers.py +4 -4
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/shadow_attribute.py +1 -1
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/sharing_groups.py +26 -21
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/sightings.py +12 -15
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/tags.py +8 -18
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/taxonomies.py +42 -16
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/user_settings.py +7 -5
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/users.py +40 -37
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/warninglists.py +12 -30
- mmisp_lib-0.10.0/src/mmisp/api_schemas/worker.py +41 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/workflows.py +1 -1
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/commandline_tool/organisation.py +15 -15
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/commandline_tool/setup.py +5 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/config.py +10 -8
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/database.py +28 -3
- mmisp_lib-0.10.0/src/mmisp/db/list_json_type.py +7 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/mixins.py +6 -4
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/admin_setting.py +1 -2
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/attribute.py +13 -12
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/auth_key.py +7 -4
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/event.py +10 -11
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/feed.py +13 -10
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/galaxy.py +10 -11
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/galaxy_cluster.py +59 -15
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/object.py +9 -10
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/organisation.py +7 -8
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/role.py +2 -6
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/server.py +1 -1
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/sharing_group.py +4 -4
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/tag.py +2 -1
- mmisp_lib-0.10.0/src/mmisp/db/models/tasks.py +23 -0
- mmisp_lib-0.10.0/src/mmisp/db/models/taxonomy.py +61 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/threat_level.py +1 -2
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/user.py +16 -16
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/user_setting.py +3 -1
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/workflow.py +2 -1
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/mypy.py +3 -1
- mmisp_lib-0.10.0/src/mmisp/db/object_json_type.py +7 -0
- mmisp_lib-0.10.0/src/mmisp/db/types.py +94 -0
- mmisp_lib-0.10.0/src/mmisp/db/uuid_type.py +7 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/attribute_search_filter.py +2 -2
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/distribution.py +7 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/galaxy_clusters.py +2 -2
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/logger.py +97 -0
- mmisp_lib-0.10.0/src/mmisp/lib/settings.py +41 -0
- mmisp_lib-0.10.0/src/mmisp/lib/standard_threat_levels.py +26 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/plugins/enrichment/data.py +5 -6
- mmisp_lib-0.10.0/src/mmisp/plugins/exceptions.py +100 -0
- mmisp_lib-0.10.0/src/mmisp/plugins/factory.py +110 -0
- mmisp_lib-0.10.0/src/mmisp/plugins/loader.py +108 -0
- mmisp_lib-0.10.0/src/mmisp/plugins/protocols.py +66 -0
- mmisp_lib-0.10.0/src/mmisp/plugins/types.py +35 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/compatibility_helpers.py +2 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/fixtures.py +46 -23
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/attribute_generator.py +8 -8
- mmisp_lib-0.10.0/src/mmisp/tests/generators/feed_generator.py +66 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/post_generator.py +4 -2
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/shadow_attribute_generator.py +2 -2
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/object_generator.py +14 -13
- mmisp_lib-0.10.0/src/mmisp/util/async_download.py +34 -0
- mmisp_lib-0.10.0/src/mmisp/util/github.py +97 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp_lib.egg-info/PKG-INFO +9 -6
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp_lib.egg-info/SOURCES.txt +12 -5
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp_lib.egg-info/requires.txt +8 -5
- mmisp_lib-0.9.0/src/mmisp/api_schemas/galaxy_common.py +0 -25
- mmisp_lib-0.9.0/src/mmisp/db/list_json_type.py +0 -31
- mmisp_lib-0.9.0/src/mmisp/db/models/taxonomy.py +0 -45
- mmisp_lib-0.9.0/src/mmisp/db/object_json_type.py +0 -34
- mmisp_lib-0.9.0/src/mmisp/db/uuid_type.py +0 -19
- mmisp_lib-0.9.0/src/mmisp/plugins/enrichment/enrichment_plugin.py +0 -41
- mmisp_lib-0.9.0/src/mmisp/plugins/exceptions.py +0 -18
- mmisp_lib-0.9.0/src/mmisp/plugins/plugin_info.py +0 -26
- mmisp_lib-0.9.0/src/mmisp/plugins/plugin_type.py +0 -12
- mmisp_lib-0.9.0/src/mmisp/tests/generators/feed_generator.py +0 -82
- mmisp_lib-0.9.0/src/mmisp/tests/generators/model_generators/event_generator.py +0 -19
- mmisp_lib-0.9.0/src/mmisp/util/models.py +0 -14
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/LICENSE +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/README.md +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/setup.cfg +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/logs.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/responses/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/responses/check_graph_response.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/responses/standard_status_response.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/server.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/api_schemas/statistics.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/commandline_tool/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/commandline_tool/main.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/commandline_tool/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/commandline_tool/user.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/additional_properties.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/all_models.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/lib.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/blocklist.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/correlation.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/identity_provider.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/log.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/noticelist.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/post.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/shadow_attribute.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/sighting.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/warninglist.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/models/workflow_blueprint.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/print_changes.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/db/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/actions.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/attributes.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/fallbacks.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/galaxies.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/permissions.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/serialisation_helper.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/standard_roles.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/lib/uuid.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/plugins/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/plugins/enrichment/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/plugins/models/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/plugins/models/attribute.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/plugins/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/attribute_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/auth_key_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/correlation_exclusions_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/correlation_value_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/default_correlation_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/galaxy_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/identity_provider_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/noticelist_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/object_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/organisation_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/over_correlating_value_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/role_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/server_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/sharing_group_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/sighting_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/tag_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/taxonomy_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/user_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/user_setting_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/warninglist_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/model_generators/workflow_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/sighting_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/tag_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/generators/taxonomies_generator.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/tests/maps.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/util/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/util/crypto.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/util/partial.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/util/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/util/uuid.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/__init__.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/execution.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/fastapi.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/graph.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/input.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/legacy.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/misp_core_format.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/modules.py +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp/workflows/py.typed +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp_lib.egg-info/dependency_links.txt +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp_lib.egg-info/entry_points.txt +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/src/mmisp_lib.egg-info/top_level.txt +0 -0
- {mmisp_lib-0.9.0 → mmisp_lib-0.10.0}/tests/test_commandline_tool.py +0 -0
@@ -1,12 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mmisp-lib
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.10.0
|
4
4
|
Requires-Python: >=3.11.0
|
5
5
|
Description-Content-Type: text/markdown
|
6
6
|
License-File: LICENSE
|
7
7
|
Requires-Dist: fastapi>=0.104.1
|
8
|
-
Requires-Dist: SQLAlchemy[asyncio]~=
|
9
|
-
Requires-Dist: pydantic==
|
8
|
+
Requires-Dist: SQLAlchemy[asyncio]~=2.0.0
|
9
|
+
Requires-Dist: pydantic==2.11.3
|
10
|
+
Requires-Dist: pydantic-settings==2.9.1
|
10
11
|
Requires-Dist: uvicorn==0.24.0.post1
|
11
12
|
Requires-Dist: python-dotenv==1.0.0
|
12
13
|
Requires-Dist: alembic==1.8.1
|
@@ -22,13 +23,15 @@ Requires-Dist: cryptography==42.0.5
|
|
22
23
|
Requires-Dist: jinja2~=3.1.4
|
23
24
|
Requires-Dist: fire
|
24
25
|
Requires-Dist: packaging
|
26
|
+
Requires-Dist: PyGithub
|
27
|
+
Requires-Dist: aiohttp
|
28
|
+
Requires-Dist: aiodns
|
25
29
|
Provides-Extra: dev
|
26
30
|
Requires-Dist: ruff>=0.3.7; extra == "dev"
|
27
31
|
Requires-Dist: mypy==1.8.0; extra == "dev"
|
28
32
|
Requires-Dist: pre-commit==3.6.0; extra == "dev"
|
29
|
-
Requires-Dist: pytest==8.
|
30
|
-
Requires-Dist: pytest-
|
31
|
-
Requires-Dist: pytest-asyncio==0.21.2; extra == "dev"
|
33
|
+
Requires-Dist: pytest==8.3.5; extra == "dev"
|
34
|
+
Requires-Dist: pytest-asyncio==0.26.0; extra == "dev"
|
32
35
|
Requires-Dist: pytest-cov==4.1.0; extra == "dev"
|
33
36
|
Requires-Dist: respx==0.20.2; extra == "dev"
|
34
37
|
Requires-Dist: mysql-connector-python==8.3.0; extra == "dev"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "mmisp-lib"
|
3
|
-
version = "0.
|
3
|
+
version = "0.10.0"
|
4
4
|
description = ""
|
5
5
|
authors = []
|
6
6
|
readme = "README.md"
|
@@ -9,8 +9,9 @@ requires-python = ">=3.11.0"
|
|
9
9
|
|
10
10
|
dependencies = [
|
11
11
|
"fastapi>=0.104.1",
|
12
|
-
"SQLAlchemy[asyncio]~=
|
13
|
-
"pydantic==
|
12
|
+
"SQLAlchemy[asyncio]~=2.0.0",
|
13
|
+
"pydantic==2.11.3",
|
14
|
+
"pydantic-settings==2.9.1",
|
14
15
|
"uvicorn==0.24.0.post1",
|
15
16
|
"python-dotenv==1.0.0",
|
16
17
|
"alembic==1.8.1",
|
@@ -26,6 +27,9 @@ dependencies = [
|
|
26
27
|
"jinja2~=3.1.4",
|
27
28
|
"fire",
|
28
29
|
"packaging",
|
30
|
+
"PyGithub",
|
31
|
+
"aiohttp",
|
32
|
+
"aiodns",
|
29
33
|
]
|
30
34
|
|
31
35
|
|
@@ -34,9 +38,9 @@ dev = [
|
|
34
38
|
"ruff>=0.3.7",
|
35
39
|
"mypy==1.8.0",
|
36
40
|
"pre-commit==3.6.0",
|
37
|
-
"pytest==8.
|
38
|
-
"pytest-test-groups",
|
39
|
-
"pytest-asyncio==0.
|
41
|
+
"pytest==8.3.5",
|
42
|
+
# "pytest-test-groups",
|
43
|
+
"pytest-asyncio==0.26.0",
|
40
44
|
"pytest-cov==4.1.0",
|
41
45
|
"respx==0.20.2",
|
42
46
|
"mysql-connector-python==8.3.0",
|
@@ -0,0 +1,48 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import Any, Self, Type
|
3
|
+
from uuid import UUID
|
4
|
+
|
5
|
+
from pydantic import BaseModel, field_serializer, field_validator
|
6
|
+
|
7
|
+
from mmisp.lib.attributes import (
|
8
|
+
AttributeCategories,
|
9
|
+
literal_valid_attribute_types,
|
10
|
+
)
|
11
|
+
from mmisp.lib.distribution import AttributeDistributionLevels
|
12
|
+
|
13
|
+
|
14
|
+
class CommonAttribute(BaseModel):
|
15
|
+
id: int
|
16
|
+
event_id: int
|
17
|
+
object_id: int
|
18
|
+
object_relation: str | None = None
|
19
|
+
category: AttributeCategories
|
20
|
+
type: literal_valid_attribute_types # type:ignore[valid-type]
|
21
|
+
value: str
|
22
|
+
to_ids: bool
|
23
|
+
uuid: UUID
|
24
|
+
timestamp: datetime
|
25
|
+
distribution: AttributeDistributionLevels
|
26
|
+
sharing_group_id: int
|
27
|
+
comment: str | None = None
|
28
|
+
deleted: bool = False
|
29
|
+
disable_correlation: bool = False
|
30
|
+
first_seen: datetime | None = None
|
31
|
+
last_seen: datetime | None = None
|
32
|
+
|
33
|
+
@field_serializer("timestamp")
|
34
|
+
def serialize_timestamp(self: Self, timestamp: datetime, _: Any) -> int:
|
35
|
+
return int(timestamp.timestamp())
|
36
|
+
|
37
|
+
@field_serializer("first_seen", "last_seen")
|
38
|
+
def serialize_timestamp_none(self: Self, timestamp: datetime, _: Any) -> int | None:
|
39
|
+
if timestamp is None:
|
40
|
+
return None
|
41
|
+
return int(timestamp.timestamp())
|
42
|
+
|
43
|
+
@field_validator("first_seen", mode="before")
|
44
|
+
@classmethod
|
45
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
46
|
+
if value == "":
|
47
|
+
return None
|
48
|
+
return value
|
@@ -1,7 +1,9 @@
|
|
1
|
-
from
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import Annotated, Any, Optional, Self, Type
|
2
3
|
|
3
|
-
from pydantic import BaseModel, Field,
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator, model_validator
|
4
5
|
|
6
|
+
from mmisp.api_schemas.attribute_common import CommonAttribute
|
5
7
|
from mmisp.lib.attributes import (
|
6
8
|
AttributeCategories,
|
7
9
|
default_category,
|
@@ -10,7 +12,7 @@ from mmisp.lib.attributes import (
|
|
10
12
|
mapper_val_safe_clsname,
|
11
13
|
to_ids,
|
12
14
|
)
|
13
|
-
from mmisp.lib.distribution import AttributeDistributionLevels
|
15
|
+
from mmisp.lib.distribution import AttributeDistributionLevels, EventDistributionLevels
|
14
16
|
|
15
17
|
|
16
18
|
class GetAttributeTag(BaseModel):
|
@@ -24,18 +26,22 @@ class GetAttributeTag(BaseModel):
|
|
24
26
|
|
25
27
|
class SearchAttributesObject(BaseModel):
|
26
28
|
id: int
|
27
|
-
distribution:
|
29
|
+
distribution: AttributeDistributionLevels
|
28
30
|
sharing_group_id: int
|
29
31
|
|
30
32
|
|
31
33
|
class SearchAttributesEvent(BaseModel):
|
32
34
|
id: int
|
33
35
|
org_id: int
|
34
|
-
distribution:
|
36
|
+
distribution: EventDistributionLevels
|
35
37
|
info: str
|
36
38
|
orgc_id: int
|
37
39
|
uuid: str
|
38
|
-
publish_timestamp:
|
40
|
+
publish_timestamp: datetime
|
41
|
+
|
42
|
+
@field_serializer("publish_timestamp")
|
43
|
+
def serialize_timestamp(self: Self, timestamp: datetime, _: Any) -> int:
|
44
|
+
return int(timestamp.timestamp())
|
39
45
|
|
40
46
|
|
41
47
|
class SearchAttributesAttributesDetails(BaseModel):
|
@@ -43,25 +49,36 @@ class SearchAttributesAttributesDetails(BaseModel):
|
|
43
49
|
event_id: int | None = None
|
44
50
|
object_id: int | None = None
|
45
51
|
object_relation: str | None = None
|
46
|
-
category:
|
52
|
+
category: AttributeCategories
|
47
53
|
type: str
|
48
54
|
value: str
|
49
55
|
to_ids: bool
|
50
56
|
uuid: str
|
51
|
-
timestamp:
|
57
|
+
timestamp: datetime
|
52
58
|
distribution: AttributeDistributionLevels
|
53
59
|
sharing_group_id: int | None = None
|
54
60
|
comment: str | None = None
|
55
61
|
deleted: bool
|
56
62
|
disable_correlation: bool
|
57
|
-
first_seen:
|
58
|
-
last_seen:
|
63
|
+
first_seen: datetime | None = None
|
64
|
+
last_seen: datetime | None = None
|
59
65
|
event_uuid: str | None = None
|
60
66
|
data: str | None = None
|
61
67
|
Event: SearchAttributesEvent | None = None
|
62
68
|
Object: SearchAttributesObject | None = None
|
63
69
|
Tag: list[GetAttributeTag] | None = None
|
64
70
|
|
71
|
+
@field_serializer("timestamp")
|
72
|
+
def serialize_timestamp(self: Self, timestamp: datetime, _: Any) -> int:
|
73
|
+
return int(timestamp.timestamp())
|
74
|
+
|
75
|
+
@field_validator("first_seen", mode="before")
|
76
|
+
@classmethod
|
77
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
78
|
+
if value == "":
|
79
|
+
return None
|
80
|
+
return value
|
81
|
+
|
65
82
|
|
66
83
|
class SearchAttributesAttributes(BaseModel):
|
67
84
|
Attribute: list[SearchAttributesAttributesDetails]
|
@@ -95,39 +112,38 @@ class RestSearchFilter(BaseModel):
|
|
95
112
|
value1: str | None = None
|
96
113
|
value2: str | None = None
|
97
114
|
type: str | None = None
|
98
|
-
category:
|
115
|
+
category: AttributeCategories | None = None
|
99
116
|
org: str | None = None
|
100
117
|
tags: list[str] | None = None
|
101
118
|
from_: str | None = None
|
102
|
-
to:
|
119
|
+
to: datetime | None = None
|
103
120
|
last: int | None = None
|
104
|
-
eventid:
|
121
|
+
eventid: int | None = None
|
105
122
|
published: bool | None = None
|
106
123
|
to_ids: bool | None = None
|
107
124
|
deleted: bool | None = None
|
108
125
|
|
109
126
|
|
110
127
|
class SearchAttributesBody(RestSearchFilter):
|
111
|
-
|
112
|
-
allow_population_by_field_name = True
|
128
|
+
model_config = ConfigDict(populate_by_name=True)
|
113
129
|
|
114
130
|
returnFormat: str = "json"
|
115
131
|
page: int | None = None
|
116
132
|
limit: int | None = None
|
117
133
|
with_attachments: Annotated[bool | None, Field(alias="withAttachments")] = None
|
118
134
|
uuid: str | None = None
|
119
|
-
publish_timestamp:
|
120
|
-
timestamp:
|
121
|
-
attribute_timestamp:
|
122
|
-
enforce_warninglist: Annotated[bool | None, Field(alias="enforceWarninglist")]
|
123
|
-
event_timestamp:
|
135
|
+
publish_timestamp: datetime | None = None
|
136
|
+
timestamp: datetime | None = None
|
137
|
+
attribute_timestamp: datetime | None = None
|
138
|
+
enforce_warninglist: Annotated[bool | None, Field(alias="enforceWarninglist")] = None
|
139
|
+
event_timestamp: datetime | None = None
|
124
140
|
threat_level_id: int | None = None
|
125
141
|
eventinfo: str | None = None
|
126
142
|
sharinggroup: list[str] | None = None
|
127
143
|
decaying_model: Annotated[str | None, Field(alias="decayingModel")] = None
|
128
144
|
score: str | None = None
|
129
|
-
first_seen:
|
130
|
-
last_seen:
|
145
|
+
first_seen: datetime | None = None
|
146
|
+
last_seen: datetime | None = None
|
131
147
|
include_event_uuid: bool | None = Field(alias="includeEventUuid", default=None)
|
132
148
|
include_event_tags: Annotated[bool | None, Field(alias="includeEventTags")] = None
|
133
149
|
include_proposals: Annotated[bool | None, Field(alias="includeProposals")] = None
|
@@ -144,6 +160,19 @@ class SearchAttributesBody(RestSearchFilter):
|
|
144
160
|
include_full_model: Annotated[bool | None, Field(alias="includeFullModel")] = None
|
145
161
|
exclude_decayed: Annotated[bool | None, Field(alias="excludeDecayed")] = None
|
146
162
|
|
163
|
+
@field_serializer("timestamp", "publish_timestamp")
|
164
|
+
def serialize_timestamp(self: Self, timestamp: datetime | None, _: Any) -> int | None:
|
165
|
+
if timestamp is None:
|
166
|
+
return None
|
167
|
+
return int(timestamp.timestamp())
|
168
|
+
|
169
|
+
@field_validator("first_seen", mode="before")
|
170
|
+
@classmethod
|
171
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
172
|
+
if value == "":
|
173
|
+
return None
|
174
|
+
return value
|
175
|
+
|
147
176
|
|
148
177
|
class RestoreAttributeResponse(BaseModel):
|
149
178
|
id: int
|
@@ -155,18 +184,27 @@ class RestoreAttributeResponse(BaseModel):
|
|
155
184
|
value: str
|
156
185
|
to_ids: bool
|
157
186
|
uuid: str
|
158
|
-
timestamp:
|
187
|
+
timestamp: datetime
|
159
188
|
distribution: AttributeDistributionLevels
|
160
189
|
sharing_group_id: int
|
161
190
|
comment: str
|
162
191
|
deleted: bool
|
163
192
|
disable_correlation: bool
|
164
|
-
first_seen:
|
165
|
-
last_seen:
|
193
|
+
first_seen: datetime | None
|
194
|
+
last_seen: datetime | None
|
166
195
|
event_uuid: str # new
|
196
|
+
model_config = ConfigDict(from_attributes=True)
|
197
|
+
|
198
|
+
@field_serializer("timestamp")
|
199
|
+
def serialize_timestamp(self: Self, timestamp: datetime, _: Any) -> int:
|
200
|
+
return int(timestamp.timestamp())
|
167
201
|
|
168
|
-
|
169
|
-
|
202
|
+
@field_validator("first_seen", mode="before")
|
203
|
+
@classmethod
|
204
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
205
|
+
if value == "":
|
206
|
+
return None
|
207
|
+
return value
|
170
208
|
|
171
209
|
|
172
210
|
class GetDescribeTypesAttributes(BaseModel):
|
@@ -190,24 +228,7 @@ class GetDescribeTypesResponse(BaseModel):
|
|
190
228
|
result: GetDescribeTypesAttributes
|
191
229
|
|
192
230
|
|
193
|
-
class GetAttributeAttributes(
|
194
|
-
id: int
|
195
|
-
event_id: int
|
196
|
-
object_id: int
|
197
|
-
object_relation: Optional[str] = Field(..., nullable=True)
|
198
|
-
category: str
|
199
|
-
type: str
|
200
|
-
value: str
|
201
|
-
to_ids: bool
|
202
|
-
uuid: str
|
203
|
-
timestamp: str
|
204
|
-
distribution: AttributeDistributionLevels
|
205
|
-
sharing_group_id: int
|
206
|
-
comment: str | None = None
|
207
|
-
deleted: bool = False
|
208
|
-
disable_correlation: bool = False
|
209
|
-
first_seen: Optional[str] = Field(..., nullable=True)
|
210
|
-
last_seen: Optional[str] = Field(..., nullable=True)
|
231
|
+
class GetAttributeAttributes(CommonAttribute):
|
211
232
|
event_uuid: str
|
212
233
|
data: str | None = None
|
213
234
|
Tag: list[GetAttributeTag] | None = None
|
@@ -215,47 +236,13 @@ class GetAttributeAttributes(BaseModel):
|
|
215
236
|
|
216
237
|
class GetAttributeResponse(BaseModel):
|
217
238
|
Attribute: GetAttributeAttributes
|
218
|
-
|
219
|
-
class Config:
|
220
|
-
orm_mode = True
|
239
|
+
model_config = ConfigDict(from_attributes=True)
|
221
240
|
|
222
241
|
|
223
|
-
class GetAllAttributesResponse(
|
224
|
-
id: int
|
225
|
-
event_id: int | None = None
|
226
|
-
object_id: int | None = None
|
227
|
-
object_relation: str | None = None
|
228
|
-
category: str | None = None
|
229
|
-
type: str
|
242
|
+
class GetAllAttributesResponse(CommonAttribute):
|
230
243
|
value1: str | None = None
|
231
244
|
value2: str | None = None
|
232
|
-
|
233
|
-
uuid: str | None = None
|
234
|
-
timestamp: str | None = None
|
235
|
-
distribution: AttributeDistributionLevels | None = None
|
236
|
-
sharing_group_id: int | None = None
|
237
|
-
comment: str | None = None
|
238
|
-
deleted: bool | None = None
|
239
|
-
disable_correlation: bool | None = None
|
240
|
-
first_seen: str | None = None
|
241
|
-
last_seen: str | None = None
|
242
|
-
value: str | None = None
|
243
|
-
|
244
|
-
# @validator("sharing_group_id", always=True, allow_reuse=True)
|
245
|
-
# @classmethod
|
246
|
-
# def check_sharing_group_id(
|
247
|
-
# cls: Type["GetAllAttributesResponse"], value: Any, values: Dict[str, Any]
|
248
|
-
# ) -> Optional[int]: # noqa: ANN101
|
249
|
-
# """
|
250
|
-
# If distribution equals 4, sharing_group_id will be shown.
|
251
|
-
# """
|
252
|
-
# distribution = values.get("distribution", None)
|
253
|
-
# if distribution == "4" and value is not None:
|
254
|
-
# return value
|
255
|
-
# return None
|
256
|
-
|
257
|
-
class Config:
|
258
|
-
orm_mode = True
|
245
|
+
model_config = ConfigDict(from_attributes=True)
|
259
246
|
|
260
247
|
|
261
248
|
class EditAttributeTag(BaseModel):
|
@@ -281,22 +268,31 @@ class EditAttributeAttributes(BaseModel):
|
|
281
268
|
value: str
|
282
269
|
to_ids: bool
|
283
270
|
uuid: str
|
284
|
-
timestamp:
|
271
|
+
timestamp: datetime
|
285
272
|
distribution: AttributeDistributionLevels
|
286
273
|
sharing_group_id: int
|
287
274
|
comment: str | None = None
|
288
275
|
deleted: bool
|
289
276
|
disable_correlation: bool
|
290
|
-
first_seen:
|
291
|
-
last_seen:
|
277
|
+
first_seen: datetime | None = None
|
278
|
+
last_seen: datetime | None = None
|
292
279
|
Tag: list[EditAttributeTag]
|
293
280
|
|
281
|
+
@field_serializer("timestamp")
|
282
|
+
def serialize_timestamp(self: Self, timestamp: datetime, _: Any) -> int:
|
283
|
+
return int(timestamp.timestamp())
|
284
|
+
|
285
|
+
@field_validator("first_seen", mode="before")
|
286
|
+
@classmethod
|
287
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
288
|
+
if value == "":
|
289
|
+
return None
|
290
|
+
return value
|
291
|
+
|
294
292
|
|
295
293
|
class EditAttributeResponse(BaseModel):
|
296
294
|
Attribute: EditAttributeAttributes
|
297
|
-
|
298
|
-
class Config:
|
299
|
-
orm_mode = True
|
295
|
+
model_config = ConfigDict(from_attributes=True)
|
300
296
|
|
301
297
|
|
302
298
|
class EditAttributeBody(BaseModel):
|
@@ -309,17 +305,28 @@ class EditAttributeBody(BaseModel):
|
|
309
305
|
category: str | None = None
|
310
306
|
to_ids: bool | None = None
|
311
307
|
uuid: str | None = None
|
312
|
-
timestamp:
|
308
|
+
timestamp: datetime | None = None
|
313
309
|
distribution: AttributeDistributionLevels | None = None
|
314
310
|
sharing_group_id: int | None = None
|
315
311
|
comment: str | None = None
|
316
312
|
deleted: bool | None = None
|
317
313
|
disable_correlation: bool | None = None
|
318
|
-
first_seen:
|
319
|
-
last_seen:
|
314
|
+
first_seen: datetime | None = None
|
315
|
+
last_seen: datetime | None = None
|
316
|
+
model_config = ConfigDict(from_attributes=True)
|
317
|
+
|
318
|
+
@field_serializer("timestamp")
|
319
|
+
def serialize_timestamp(self: Self, timestamp: datetime | None, _: Any) -> int | None:
|
320
|
+
if timestamp is None:
|
321
|
+
return None
|
322
|
+
return int(timestamp.timestamp())
|
320
323
|
|
321
|
-
|
322
|
-
|
324
|
+
@field_validator("first_seen", mode="before")
|
325
|
+
@classmethod
|
326
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
327
|
+
if value == "":
|
328
|
+
return None
|
329
|
+
return value
|
323
330
|
|
324
331
|
|
325
332
|
class DeleteSelectedAttributeResponse(BaseModel):
|
@@ -329,56 +336,31 @@ class DeleteSelectedAttributeResponse(BaseModel):
|
|
329
336
|
message: str
|
330
337
|
url: str
|
331
338
|
id: str
|
332
|
-
|
333
|
-
class Config:
|
334
|
-
orm_mode = True
|
339
|
+
model_config = ConfigDict(from_attributes=True)
|
335
340
|
|
336
341
|
|
337
342
|
class DeleteAttributeResponse(BaseModel):
|
338
343
|
message: str
|
339
|
-
|
340
|
-
class Config:
|
341
|
-
orm_mode = True
|
344
|
+
model_config = ConfigDict(from_attributes=True)
|
342
345
|
|
343
346
|
|
344
347
|
class AddRemoveTagAttributeResponse(BaseModel):
|
345
348
|
saved: bool
|
346
|
-
success: Optional[str]
|
347
|
-
check_publish: Optional[bool]
|
348
|
-
errors: Optional[str]
|
349
|
-
|
350
|
-
class Config:
|
351
|
-
orm_mode = True
|
349
|
+
success: Optional[str] = None
|
350
|
+
check_publish: Optional[bool] = None
|
351
|
+
errors: Optional[str] = None
|
352
|
+
model_config = ConfigDict(from_attributes=True)
|
352
353
|
|
353
354
|
|
354
|
-
class AddAttributeAttributes(
|
355
|
-
id: int
|
356
|
-
event_id: int
|
357
|
-
object_id: int
|
358
|
-
object_relation: Optional[str] = Field(..., nullable=True)
|
359
|
-
category: str
|
360
|
-
type: str
|
361
|
-
value: str
|
355
|
+
class AddAttributeAttributes(CommonAttribute):
|
362
356
|
value1: str
|
363
357
|
value2: str
|
364
|
-
to_ids: bool
|
365
|
-
uuid: str
|
366
|
-
timestamp: str
|
367
|
-
distribution: AttributeDistributionLevels
|
368
|
-
sharing_group_id: int
|
369
|
-
comment: str | None = None
|
370
|
-
deleted: bool
|
371
|
-
disable_correlation: bool
|
372
|
-
first_seen: str | None = None
|
373
|
-
last_seen: str | None = None
|
374
358
|
attribute_tag: list[str] | None = Field(default_factory=list, alias="AttributeTag")
|
375
359
|
|
376
360
|
|
377
361
|
class AddAttributeResponse(BaseModel):
|
378
362
|
Attribute: AddAttributeAttributes
|
379
|
-
|
380
|
-
class Config:
|
381
|
-
orm_mode = True
|
363
|
+
model_config = ConfigDict(from_attributes=True)
|
382
364
|
|
383
365
|
|
384
366
|
class AddAttributeBody(BaseModel):
|
@@ -392,32 +374,47 @@ class AddAttributeBody(BaseModel):
|
|
392
374
|
category: str | None = None
|
393
375
|
to_ids: bool | None = None
|
394
376
|
uuid: str | None = None
|
395
|
-
timestamp:
|
377
|
+
timestamp: datetime | None = None
|
396
378
|
distribution: AttributeDistributionLevels | None = None
|
397
379
|
sharing_group_id: int | None = None
|
398
380
|
comment: str | None = None
|
399
381
|
deleted: bool | None = None
|
400
382
|
disable_correlation: bool | None = None
|
401
|
-
first_seen:
|
402
|
-
last_seen:
|
383
|
+
first_seen: datetime | None = None
|
384
|
+
last_seen: datetime | None = None
|
403
385
|
|
404
|
-
@
|
405
|
-
|
406
|
-
|
407
|
-
required_values: list[str] = [str(data.get("value")), str(data.get("value1"))]
|
408
|
-
if all(item is None for item in required_values):
|
386
|
+
@model_validator(mode="after")
|
387
|
+
def ensure_value_or_value1_is_set(self: Self) -> Self:
|
388
|
+
if self.value is None and self.value1 is None:
|
409
389
|
raise ValueError("value or value1 has to be set")
|
410
|
-
return
|
390
|
+
return self
|
391
|
+
|
392
|
+
@field_serializer("timestamp")
|
393
|
+
def serialize_timestamp(self: Self, timestamp: datetime | None, _: Any) -> int | None:
|
394
|
+
if timestamp is None:
|
395
|
+
return None
|
396
|
+
return int(timestamp.timestamp())
|
397
|
+
|
398
|
+
@field_validator("first_seen", mode="before")
|
399
|
+
@classmethod
|
400
|
+
def empty_string_to_none(cls: Type[Self], value: Any) -> Any:
|
401
|
+
if value == "":
|
402
|
+
return None
|
403
|
+
return value
|
411
404
|
|
412
405
|
|
413
406
|
GetAttributeStatisticsTypesResponseAttrs = {x: Field(default=None) for x in mapper_val_safe_clsname.keys()}
|
414
|
-
GetAttributeStatisticsTypesResponseAttrs["__annotations__"] = {
|
407
|
+
GetAttributeStatisticsTypesResponseAttrs["__annotations__"] = {
|
408
|
+
x: str | int | None for x in mapper_val_safe_clsname.keys()
|
409
|
+
}
|
415
410
|
GetAttributeStatisticsTypesResponse = type( # type: ignore
|
416
411
|
"GetAttributeStatisticsTypesResponse", (BaseModel,), GetAttributeStatisticsTypesResponseAttrs
|
417
412
|
)
|
418
413
|
|
419
414
|
GetAttributeStatisticsCategoriesResponseAttrs = {x.value: Field(default=None) for x in AttributeCategories}
|
420
|
-
GetAttributeStatisticsCategoriesResponseAttrs["__annotations__"] = {
|
415
|
+
GetAttributeStatisticsCategoriesResponseAttrs["__annotations__"] = {
|
416
|
+
x.value: str | int | None for x in AttributeCategories
|
417
|
+
}
|
421
418
|
GetAttributeStatisticsCategoriesResponse = type( # type: ignore
|
422
419
|
"GetAttributeStatisticsCategoriesResponse", (BaseModel,), GetAttributeStatisticsCategoriesResponseAttrs
|
423
420
|
)
|