mmisp-lib 0.3.0__tar.gz → 0.4.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.3.0 → mmisp_lib-0.4.0}/PKG-INFO +2 -2
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/pyproject.toml +3 -2
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/attributes.py +12 -11
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/events.py +7 -5
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/organisations.py +1 -1
- mmisp_lib-0.4.0/src/mmisp/db/additional_properties.py +10 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/all_models.py +2 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/mixins.py +2 -1
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/attribute.py +81 -3
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/event.py +35 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/galaxy.py +7 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/galaxy_cluster.py +32 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/object.py +14 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/organisation.py +28 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/tag.py +4 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/user.py +4 -0
- mmisp_lib-0.4.0/src/mmisp/lib/attribute_search_filter.py +60 -0
- mmisp_lib-0.4.0/src/mmisp/tests/compatibility_helpers.py +56 -0
- mmisp_lib-0.4.0/src/mmisp/tests/fixtures.py +787 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/feed_generator.py +82 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/attribute_generator.py +5 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/auth_key_generator.py +18 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/event_generator.py +16 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/galaxy_generator.py +11 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/identity_provider_generator.py +16 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/noticelist_generator.py +26 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/organisation_generator.py +20 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/role_generator.py +106 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/server_generator.py +27 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/sharing_group_generator.py +16 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/tag_generator.py +15 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/taxonomy_generator.py +40 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/user_generator.py +27 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/user_setting_generator.py +20 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/warninglist_generator.py +31 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/model_generators/workflow_generator.py +414 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/object_generator.py +180 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/sighting_generator.py +47 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/tag_generator.py +103 -0
- mmisp_lib-0.4.0/src/mmisp/tests/generators/taxonomies_generator.py +61 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/execution.py +5 -3
- mmisp_lib-0.4.0/src/mmisp/workflows/py.typed +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp_lib.egg-info/PKG-INFO +2 -2
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp_lib.egg-info/SOURCES.txt +26 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp_lib.egg-info/requires.txt +1 -1
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/tests/test_commandline_tool.py +1 -1
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/LICENSE +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/README.md +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/setup.cfg +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/auth_keys.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/authentication.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/common.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/feeds.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/galaxies.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/galaxy_clusters.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/jobs.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/logs.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/noticelists.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/objects.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/py.typed +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/responses/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/responses/check_graph_response.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/responses/standard_status_response.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/roles.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/servers.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/sharing_groups.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/sightings.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/statistics.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/tags.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/taxonomies.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/user_settings.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/users.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/warninglists.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/api_schemas/workflows.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/commandline_tool/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/commandline_tool/main.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/commandline_tool/organisation.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/commandline_tool/py.typed +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/commandline_tool/setup.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/commandline_tool/user.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/config.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/database.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/admin_setting.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/auth_key.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/feed.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/identity_provider.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/log.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/noticelist.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/role.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/server.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/sharing_group.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/sighting.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/taxonomy.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/user_setting.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/warninglist.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/workflow.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/models/workflow_blueprint.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/mypy.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/print_changes.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/db/py.typed +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/actions.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/attributes.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/logging.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/permissions.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/py.typed +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/lib/uuid.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/plugins/py.typed +0 -0
- {mmisp_lib-0.3.0/src/mmisp/util → mmisp_lib-0.4.0/src/mmisp/tests}/__init__.py +0 -0
- {mmisp_lib-0.3.0/src/mmisp/workflows → mmisp_lib-0.4.0/src/mmisp/util}/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/util/crypto.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/util/models.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/util/partial.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/util/py.typed +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/util/uuid.py +0 -0
- /mmisp_lib-0.3.0/src/mmisp/workflows/py.typed → /mmisp_lib-0.4.0/src/mmisp/workflows/__init__.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/fastapi.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/graph.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/input.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/legacy.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/misp_core_format.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp/workflows/modules.py +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp_lib.egg-info/dependency_links.txt +0 -0
- {mmisp_lib-0.3.0 → mmisp_lib-0.4.0}/src/mmisp_lib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: mmisp-lib
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Requires-Python: >=3.11.0
|
5
5
|
Description-Content-Type: text/markdown
|
6
6
|
License-File: LICENSE
|
@@ -27,7 +27,7 @@ Requires-Dist: mypy==1.8.0; extra == "dev"
|
|
27
27
|
Requires-Dist: pre-commit==3.6.0; extra == "dev"
|
28
28
|
Requires-Dist: pytest==8.0.0; extra == "dev"
|
29
29
|
Requires-Dist: pytest-test-groups; extra == "dev"
|
30
|
-
Requires-Dist: pytest-asyncio==0.
|
30
|
+
Requires-Dist: pytest-asyncio==0.21.2; extra == "dev"
|
31
31
|
Requires-Dist: pytest-cov==4.1.0; extra == "dev"
|
32
32
|
Requires-Dist: respx==0.20.2; extra == "dev"
|
33
33
|
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.4.0"
|
4
4
|
description = ""
|
5
5
|
authors = []
|
6
6
|
readme = "README.md"
|
@@ -35,7 +35,7 @@ dev = [
|
|
35
35
|
"pre-commit==3.6.0",
|
36
36
|
"pytest==8.0.0",
|
37
37
|
"pytest-test-groups",
|
38
|
-
"pytest-asyncio==0.
|
38
|
+
"pytest-asyncio==0.21.2",
|
39
39
|
"pytest-cov==4.1.0",
|
40
40
|
"respx==0.20.2",
|
41
41
|
"mysql-connector-python==8.3.0",
|
@@ -63,6 +63,7 @@ ignore = ["ANN002", "ANN003", "ANN401"]
|
|
63
63
|
|
64
64
|
[tool.ruff.lint.per-file-ignores]
|
65
65
|
"tests/**" = ["ANN001", "ANN201", "ANN202", "S101"]
|
66
|
+
"src/mmisp/tests/**" = ["ANN001", "ANN201", "ANN202", "S101"]
|
66
67
|
|
67
68
|
[tool.coverage.run]
|
68
69
|
concurrency = ["greenlet", "thread"]
|
@@ -34,6 +34,7 @@ class SearchAttributesEvent(BaseModel):
|
|
34
34
|
info: str
|
35
35
|
orgc_id: str
|
36
36
|
uuid: str
|
37
|
+
publish_timestamp: int
|
37
38
|
|
38
39
|
|
39
40
|
class SearchAttributesAttributesDetails(BaseModel):
|
@@ -56,7 +57,7 @@ class SearchAttributesAttributesDetails(BaseModel):
|
|
56
57
|
last_seen: str | None = None
|
57
58
|
Event: SearchAttributesEvent | None = None
|
58
59
|
Object: SearchAttributesObject | None = None
|
59
|
-
Tag: list[GetAttributeTag] =
|
60
|
+
Tag: list[GetAttributeTag] | None = None
|
60
61
|
|
61
62
|
|
62
63
|
class SearchAttributesAttributes(BaseModel):
|
@@ -86,10 +87,7 @@ class SearchAttributesModelOverrides(BaseModel):
|
|
86
87
|
base_score_config: SearchAttributesModelOverridesBaseScoreConfig
|
87
88
|
|
88
89
|
|
89
|
-
class
|
90
|
-
returnFormat: str = "json"
|
91
|
-
page: int | None = None
|
92
|
-
limit: int | None = None
|
90
|
+
class RestSearchFilter(BaseModel):
|
93
91
|
value: str | None = None
|
94
92
|
value1: str | None = None
|
95
93
|
value2: str | None = None
|
@@ -101,15 +99,21 @@ class SearchAttributesBody(BaseModel):
|
|
101
99
|
to: str | None = None
|
102
100
|
last: int | None = None
|
103
101
|
eventid: str | None = None
|
102
|
+
published: bool | None = None
|
103
|
+
to_ids: bool | None = None
|
104
|
+
deleted: bool | None = None
|
105
|
+
|
106
|
+
|
107
|
+
class SearchAttributesBody(RestSearchFilter):
|
108
|
+
returnFormat: str = "json"
|
109
|
+
page: int | None = None
|
110
|
+
limit: int | None = None
|
104
111
|
with_attachments: Annotated[bool | None, Field(alias="withAttachments")] = None
|
105
112
|
uuid: str | None = None
|
106
113
|
publish_timestamp: str | None = None
|
107
|
-
published: bool | None = None
|
108
114
|
timestamp: str | None = None
|
109
115
|
attribute_timestamp: str | None = None
|
110
116
|
enforce_warninglist: Annotated[bool | None, Field(alias="enforceWarninglist")]
|
111
|
-
to_ids: bool | None = None
|
112
|
-
deleted: bool | None = None
|
113
117
|
event_timestamp: str | None = None
|
114
118
|
threat_level_id: str | None = None
|
115
119
|
eventinfo: str | None = None
|
@@ -134,9 +138,6 @@ class SearchAttributesBody(BaseModel):
|
|
134
138
|
include_full_model: Annotated[bool | None, Field(alias="includeFullModel")] = None
|
135
139
|
exclude_decayed: Annotated[bool | None, Field(alias="excludeDecayed")] = None
|
136
140
|
|
137
|
-
class Config:
|
138
|
-
orm_mode = True
|
139
|
-
|
140
141
|
|
141
142
|
class RestoreAttributeResponse(BaseModel):
|
142
143
|
id: str
|
@@ -1,3 +1,5 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
|
1
3
|
from pydantic import BaseModel, PositiveInt, conint
|
2
4
|
|
3
5
|
from mmisp.api_schemas.organisations import Organisation
|
@@ -89,7 +91,7 @@ class GetAllEventsGalaxyCluster(BaseModel):
|
|
89
91
|
meta: AddEditGetEventGalaxyClusterMeta | None = None
|
90
92
|
tag_id: str
|
91
93
|
local: bool | None = None
|
92
|
-
relationship_type: str | None = None
|
94
|
+
relationship_type: bool | str | None = None
|
93
95
|
|
94
96
|
|
95
97
|
class AddEditGetEventGalaxyClusterRelationTag(BaseModel):
|
@@ -149,7 +151,7 @@ class AddEditGetEventGalaxyCluster(BaseModel):
|
|
149
151
|
attribute_tag_id: str | None = None
|
150
152
|
event_tag_id: str | None = None
|
151
153
|
local: bool | None = None
|
152
|
-
relationship_type: str = ""
|
154
|
+
relationship_type: bool | str = ""
|
153
155
|
|
154
156
|
|
155
157
|
class AddEditGetEventGalaxy(BaseModel):
|
@@ -186,7 +188,7 @@ class AddEditGetEventTag(BaseModel):
|
|
186
188
|
is_custom_galaxy: bool
|
187
189
|
local_only: bool
|
188
190
|
local: bool
|
189
|
-
relationship_type: str | None = None
|
191
|
+
relationship_type: bool | str | None = None
|
190
192
|
|
191
193
|
|
192
194
|
class AddEditGetEventAttribute(BaseModel):
|
@@ -288,7 +290,7 @@ class AddEditGetEventResponse(BaseModel):
|
|
288
290
|
Event: AddEditGetEventDetails
|
289
291
|
|
290
292
|
class Config:
|
291
|
-
|
293
|
+
json_encoders = {datetime: lambda v: v.strftime("%Y-%m-%d %H:%M:%S")}
|
292
294
|
|
293
295
|
|
294
296
|
class GetAllEventsOrg(BaseModel):
|
@@ -456,7 +458,7 @@ class GetAllEventsEventTag(BaseModel):
|
|
456
458
|
event_id: str
|
457
459
|
tag_id: str
|
458
460
|
local: bool
|
459
|
-
relationship_type: str | None = None
|
461
|
+
relationship_type: bool | str | None = None
|
460
462
|
Tag: GetAllEventsEventTagTag | None = None
|
461
463
|
|
462
464
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
from sqlalchemy import func, select
|
2
|
+
from sqlalchemy.orm import column_property
|
3
|
+
|
4
|
+
from mmisp.db.models.organisation import Organisation
|
5
|
+
from mmisp.db.models.user import User
|
6
|
+
|
7
|
+
Organisation.user_count = column_property(
|
8
|
+
select(func.count(User.id)).where(User.org_id == Organisation.id).correlate_except(User).scalar_subquery(),
|
9
|
+
deferred=False,
|
10
|
+
)
|
@@ -6,9 +6,10 @@ from sqlalchemy.ext.hybrid import hybrid_property
|
|
6
6
|
|
7
7
|
class DictMixin:
|
8
8
|
def asdict(self: Self) -> dict:
|
9
|
+
unloaded = inspect(self).unloaded
|
9
10
|
d = {}
|
10
11
|
for key in self.__mapper__.c.keys(): # type:ignore[attr-defined]
|
11
|
-
if not key.startswith("_"):
|
12
|
+
if not key.startswith("_") and key not in unloaded:
|
12
13
|
d[key] = getattr(self, key)
|
13
14
|
|
14
15
|
for key, prop in inspect(self.__class__).all_orm_descriptors.items(): # type:ignore[union-attr]
|
@@ -1,7 +1,9 @@
|
|
1
|
+
import typing
|
1
2
|
from typing import Self, Type
|
2
3
|
|
3
|
-
from sqlalchemy import BigInteger, Boolean, ForeignKey, Integer, String, Text
|
4
|
-
from sqlalchemy.ext.
|
4
|
+
from sqlalchemy import BigInteger, Boolean, ForeignKey, Integer, String, Text, or_
|
5
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
6
|
+
from sqlalchemy.ext.hybrid import Comparator, hybrid_property
|
5
7
|
from sqlalchemy.orm import relationship
|
6
8
|
from sqlalchemy.orm.decl_api import DeclarativeMeta
|
7
9
|
|
@@ -14,6 +16,20 @@ from ..database import Base
|
|
14
16
|
from .event import Event
|
15
17
|
from .tag import Tag
|
16
18
|
|
19
|
+
if typing.TYPE_CHECKING:
|
20
|
+
from sqlalchemy import ColumnExpressionArgument
|
21
|
+
else:
|
22
|
+
ColumnExpressionArgument = typing.Any
|
23
|
+
|
24
|
+
|
25
|
+
class AttributeComparator(Comparator):
|
26
|
+
def __init__(self: Self, cls: typing.Any) -> None:
|
27
|
+
self.cls = cls
|
28
|
+
|
29
|
+
def __eq__(self: Self, other: typing.Any) -> ColumnExpressionArgument:
|
30
|
+
# Overriding equality to check if the value matches either value1 or value1 + "|" + value2
|
31
|
+
return or_(self.cls.value1 == other, self.cls.value1 + "|" + self.cls.value2 == other)
|
32
|
+
|
17
33
|
|
18
34
|
class Attribute(Base, DictMixin):
|
19
35
|
__tablename__ = "attributes"
|
@@ -40,11 +56,57 @@ class Attribute(Base, DictMixin):
|
|
40
56
|
last_seen: Mapped[int] = mapped_column(BigInteger, index=True)
|
41
57
|
|
42
58
|
event = relationship("Event", back_populates="attributes", lazy="joined") # type:ignore[var-annotated]
|
59
|
+
mispobject = relationship(
|
60
|
+
"Object",
|
61
|
+
primaryjoin="Attribute.object_id == Object.id",
|
62
|
+
back_populates="attributes",
|
63
|
+
lazy="joined",
|
64
|
+
foreign_keys="Attribute.object_id",
|
65
|
+
) # type:ignore[var-annotated]
|
66
|
+
tags = relationship("Tag", secondary="attribute_tags", lazy="raise_on_sql", viewonly=True)
|
67
|
+
attributetags = relationship(
|
68
|
+
"AttributeTag",
|
69
|
+
primaryjoin="Attribute.id == AttributeTag.attribute_id",
|
70
|
+
back_populates="attribute",
|
71
|
+
lazy="raise_on_sql",
|
72
|
+
viewonly=True,
|
73
|
+
)
|
74
|
+
attributetags_galaxy = relationship(
|
75
|
+
"AttributeTag",
|
76
|
+
primaryjoin="and_(Attribute.id == AttributeTag.attribute_id, Tag.is_galaxy)",
|
77
|
+
secondary="join(AttributeTag, Tag, AttributeTag.tag_id == Tag.id)",
|
78
|
+
secondaryjoin="AttributeTag.tag_id == Tag.id",
|
79
|
+
lazy="raise_on_sql",
|
80
|
+
viewonly=True,
|
81
|
+
)
|
82
|
+
|
83
|
+
galaxy_tags = relationship(
|
84
|
+
"Tag",
|
85
|
+
secondary="attribute_tags",
|
86
|
+
secondaryjoin="and_(AttributeTag.tag_id == Tag.id, Tag.is_galaxy)",
|
87
|
+
lazy="raise_on_sql",
|
88
|
+
overlaps="tags, events",
|
89
|
+
viewonly=True,
|
90
|
+
)
|
91
|
+
local_tags = relationship(
|
92
|
+
"Tag",
|
93
|
+
secondary="attribute_tags",
|
94
|
+
secondaryjoin="and_(AttributeTag.tag_id == Tag.id, AttributeTag.local)",
|
95
|
+
lazy="raise_on_sql",
|
96
|
+
viewonly=True,
|
97
|
+
)
|
98
|
+
nonlocal_tags = relationship(
|
99
|
+
"Tag",
|
100
|
+
secondary="attribute_tags",
|
101
|
+
secondaryjoin="and_(AttributeTag.tag_id == Tag.id, not_(AttributeTag.local))",
|
102
|
+
lazy="raise_on_sql",
|
103
|
+
viewonly=True,
|
104
|
+
)
|
43
105
|
|
44
106
|
__mapper_args__ = {"polymorphic_on": "type"}
|
45
107
|
|
46
108
|
def __init__(self: Self, *arg, **kwargs) -> None:
|
47
|
-
if
|
109
|
+
if "value" in kwargs:
|
48
110
|
split_val = kwargs["value"].split("|", 1)
|
49
111
|
kwargs["value1"] = split_val[0]
|
50
112
|
if len(split_val) == 2:
|
@@ -52,6 +114,14 @@ class Attribute(Base, DictMixin):
|
|
52
114
|
|
53
115
|
super().__init__(*arg, **kwargs)
|
54
116
|
|
117
|
+
async def add_tag(self: Self, db: AsyncSession, tag: "Tag", local: bool = False) -> "AttributeTag":
|
118
|
+
if tag.local_only:
|
119
|
+
local = True
|
120
|
+
attribute_tag = AttributeTag(attribute=self, tag=tag, event_id=self.event_id, local=local)
|
121
|
+
db.add(attribute_tag)
|
122
|
+
await db.commit()
|
123
|
+
return attribute_tag
|
124
|
+
|
55
125
|
@property
|
56
126
|
def event_uuid(self: "Attribute") -> str:
|
57
127
|
return self.event.uuid
|
@@ -69,6 +139,10 @@ class Attribute(Base, DictMixin):
|
|
69
139
|
if len(split) == 2:
|
70
140
|
self.value2 = split[1]
|
71
141
|
|
142
|
+
@value.comparator
|
143
|
+
def value(cls: Self) -> AttributeComparator:
|
144
|
+
return AttributeComparator(cls)
|
145
|
+
|
72
146
|
|
73
147
|
class AttributeTag(Base):
|
74
148
|
__tablename__ = "attribute_tags"
|
@@ -80,6 +154,10 @@ class AttributeTag(Base):
|
|
80
154
|
event_id: Mapped[int] = mapped_column(Integer, ForeignKey(Event.id, ondelete="CASCADE"), nullable=False, index=True)
|
81
155
|
tag_id: Mapped[int] = mapped_column(Integer, ForeignKey(Tag.id, ondelete="CASCADE"), nullable=False, index=True)
|
82
156
|
local: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
157
|
+
relationship_type: Mapped[str] = mapped_column(String(191), nullable=True)
|
158
|
+
|
159
|
+
attribute = relationship("Attribute", back_populates="attributetags", lazy="raise_on_sql")
|
160
|
+
tag = relationship("Tag", back_populates="attributetags", lazy="raise_on_sql")
|
83
161
|
|
84
162
|
|
85
163
|
class AttributeMeta(DeclarativeMeta):
|
@@ -38,6 +38,37 @@ class Event(Base):
|
|
38
38
|
protected: Mapped[bool] = mapped_column(Boolean)
|
39
39
|
|
40
40
|
attributes = relationship("Attribute", back_populates="event") # type:ignore[assignment,var-annotated]
|
41
|
+
mispobjects = relationship("Object", back_populates="event") # type:ignore[assignment,var-annotated]
|
42
|
+
org = relationship(
|
43
|
+
"Organisation", primaryjoin="Event.org_id == Organisation.id", back_populates="events", lazy="raise_on_sql"
|
44
|
+
) # type:ignore[assignment,var-annotated]
|
45
|
+
orgc = relationship(
|
46
|
+
"Organisation",
|
47
|
+
primaryjoin="Event.orgc_id == Organisation.id",
|
48
|
+
back_populates="events_created",
|
49
|
+
lazy="raise_on_sql",
|
50
|
+
) # type:ignore[assignment,var-annotated]
|
51
|
+
creator = relationship("User", primaryjoin="Event.user_id == User.id", lazy="selectin")
|
52
|
+
tags = relationship("Tag", secondary="event_tags", lazy="raise_on_sql", viewonly=True)
|
53
|
+
eventtags = relationship(
|
54
|
+
"EventTag", primaryjoin="Event.id == EventTag.event_id", lazy="raise_on_sql", viewonly=True
|
55
|
+
)
|
56
|
+
eventtags_galaxy = relationship(
|
57
|
+
"EventTag",
|
58
|
+
primaryjoin="and_(Event.id == EventTag.event_id, Tag.is_galaxy)",
|
59
|
+
secondary="join(EventTag, Tag, EventTag.tag_id == Tag.id)",
|
60
|
+
secondaryjoin="EventTag.tag_id == Tag.id",
|
61
|
+
lazy="raise_on_sql",
|
62
|
+
viewonly=True,
|
63
|
+
)
|
64
|
+
galaxy_tags = relationship(
|
65
|
+
"Tag",
|
66
|
+
secondary="event_tags",
|
67
|
+
secondaryjoin="and_(EventTag.tag_id == Tag.id, Tag.is_galaxy)",
|
68
|
+
lazy="raise_on_sql",
|
69
|
+
overlaps="tags, events",
|
70
|
+
viewonly=True,
|
71
|
+
)
|
41
72
|
|
42
73
|
|
43
74
|
class EventReport(Base):
|
@@ -61,3 +92,7 @@ class EventTag(Base):
|
|
61
92
|
event_id: Mapped[int] = mapped_column(Integer, ForeignKey(Event.id, ondelete="CASCADE"), nullable=False, index=True)
|
62
93
|
tag_id: Mapped[int] = mapped_column(Integer, ForeignKey(Tag.id, ondelete="CASCADE"), nullable=False, index=True)
|
63
94
|
local: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
95
|
+
relationship_type: Mapped[str] = mapped_column(String(191), nullable=True)
|
96
|
+
|
97
|
+
event = relationship("Event", back_populates="eventtags", lazy="raise_on_sql", viewonly=True)
|
98
|
+
tag = relationship("Tag", back_populates="eventtags", lazy="raise_on_sql", viewonly=True)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from sqlalchemy import Boolean, Integer, String, Text
|
2
|
+
from sqlalchemy.orm import relationship
|
2
3
|
|
3
4
|
from mmisp.db.mypy import Mapped, mapped_column
|
4
5
|
from mmisp.lib.uuid import uuid
|
@@ -21,3 +22,9 @@ class Galaxy(Base):
|
|
21
22
|
"""must be serialized"""
|
22
23
|
enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
23
24
|
local_only: Mapped[bool] = mapped_column(Boolean, default=False)
|
25
|
+
|
26
|
+
galaxy_clusters = relationship(
|
27
|
+
"GalaxyCluster",
|
28
|
+
back_populates="galaxy",
|
29
|
+
lazy="raise_on_sql",
|
30
|
+
) # type:ignore[assignment,var-annotated]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from sqlalchemy import Boolean, ForeignKey, Integer, String, Text
|
2
|
+
from sqlalchemy.orm import relationship
|
2
3
|
|
3
4
|
from mmisp.db.mypy import Mapped, mapped_column
|
4
5
|
from mmisp.lib.uuid import uuid
|
@@ -34,6 +35,31 @@ class GalaxyCluster(Base):
|
|
34
35
|
published: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
35
36
|
deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
36
37
|
|
38
|
+
org = relationship(
|
39
|
+
"Organisation",
|
40
|
+
primaryjoin="GalaxyCluster.org_id == Organisation.id",
|
41
|
+
back_populates="galaxy_clusters",
|
42
|
+
lazy="raise_on_sql",
|
43
|
+
foreign_keys="GalaxyCluster.org_id",
|
44
|
+
) # type:ignore[assignment,var-annotated]
|
45
|
+
orgc = relationship(
|
46
|
+
"Organisation",
|
47
|
+
primaryjoin="GalaxyCluster.orgc_id == Organisation.id",
|
48
|
+
back_populates="galaxy_clusters_created",
|
49
|
+
lazy="raise_on_sql",
|
50
|
+
foreign_keys="GalaxyCluster.orgc_id",
|
51
|
+
) # type:ignore[assignment,var-annotated]
|
52
|
+
galaxy = relationship(
|
53
|
+
"Galaxy",
|
54
|
+
back_populates="galaxy_clusters",
|
55
|
+
lazy="raise_on_sql",
|
56
|
+
) # type:ignore[assignment,var-annotated]
|
57
|
+
galaxy_elements = relationship(
|
58
|
+
"GalaxyElement",
|
59
|
+
back_populates="galaxy_cluster",
|
60
|
+
lazy="raise_on_sql",
|
61
|
+
) # type:ignore[assignment,var-annotated]
|
62
|
+
|
37
63
|
|
38
64
|
class GalaxyElement(Base):
|
39
65
|
__tablename__ = "galaxy_elements"
|
@@ -45,6 +71,12 @@ class GalaxyElement(Base):
|
|
45
71
|
key: Mapped[str] = mapped_column(String(255), nullable=False, default="", index=True)
|
46
72
|
value: Mapped[str] = mapped_column(Text, nullable=False)
|
47
73
|
|
74
|
+
galaxy_cluster = relationship(
|
75
|
+
"GalaxyCluster",
|
76
|
+
back_populates="galaxy_elements",
|
77
|
+
lazy="raise_on_sql",
|
78
|
+
) # type:ignore[assignment,var-annotated]
|
79
|
+
|
48
80
|
|
49
81
|
class GalaxyReference(Base):
|
50
82
|
__tablename__ = "galaxy_reference"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from sqlalchemy import Boolean, ForeignKey, Integer, String
|
2
|
+
from sqlalchemy.orm import relationship
|
2
3
|
|
3
4
|
from mmisp.db.database import Base
|
4
5
|
from mmisp.db.mixins import DictMixin
|
@@ -25,6 +26,19 @@ class Object(Base, DictMixin):
|
|
25
26
|
first_seen: Mapped[int] = mapped_column(Integer, index=True, default=None)
|
26
27
|
last_seen: Mapped[int] = mapped_column(Integer, index=True, default=None)
|
27
28
|
|
29
|
+
attributes = relationship(
|
30
|
+
"Attribute",
|
31
|
+
primaryjoin="Object.id == Attribute.object_id",
|
32
|
+
back_populates="mispobject",
|
33
|
+
lazy="raise_on_sql",
|
34
|
+
foreign_keys="Attribute.object_id",
|
35
|
+
) # type:ignore[var-annotated]
|
36
|
+
event = relationship(
|
37
|
+
"Event",
|
38
|
+
back_populates="mispobjects",
|
39
|
+
lazy="raise_on_sql",
|
40
|
+
) # type:ignore[var-annotated]
|
41
|
+
|
28
42
|
|
29
43
|
class ObjectTemplate(Base, DictMixin):
|
30
44
|
__tablename__ = "object_templates"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
|
3
3
|
from sqlalchemy import Boolean, DateTime, Integer, String, Text
|
4
|
+
from sqlalchemy.orm import relationship
|
4
5
|
|
5
6
|
from mmisp.db.mixins import DictMixin
|
6
7
|
from mmisp.db.mypy import Mapped, mapped_column
|
@@ -27,3 +28,30 @@ class Organisation(Base, DictMixin):
|
|
27
28
|
local: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
28
29
|
restricted_to_domain: Mapped[str] = mapped_column(Text)
|
29
30
|
landingpage: Mapped[str] = mapped_column(Text)
|
31
|
+
|
32
|
+
# Relationship to users
|
33
|
+
users = relationship("User", back_populates="org", lazy="raise_on_sql")
|
34
|
+
creator = relationship(
|
35
|
+
"User", primaryjoin="Organisation.created_by == User.id", foreign_keys=created_by, lazy="selectin"
|
36
|
+
)
|
37
|
+
events = relationship(
|
38
|
+
"Event", primaryjoin="Organisation.id == Event.org_id", back_populates="org", lazy="raise_on_sql"
|
39
|
+
) # type:ignore[assignment,var-annotated]
|
40
|
+
events_created = relationship(
|
41
|
+
"Event", primaryjoin="Organisation.id == Event.orgc_id", back_populates="orgc", lazy="raise_on_sql"
|
42
|
+
) # type:ignore[assignment,var-annotated]
|
43
|
+
|
44
|
+
galaxy_clusters = relationship(
|
45
|
+
"GalaxyCluster",
|
46
|
+
primaryjoin="Organisation.id == GalaxyCluster.org_id",
|
47
|
+
back_populates="org",
|
48
|
+
lazy="raise_on_sql",
|
49
|
+
foreign_keys="GalaxyCluster.org_id",
|
50
|
+
) # type:ignore[assignment,var-annotated]
|
51
|
+
galaxy_clusters_created = relationship(
|
52
|
+
"GalaxyCluster",
|
53
|
+
primaryjoin="Organisation.id == GalaxyCluster.orgc_id",
|
54
|
+
back_populates="orgc",
|
55
|
+
lazy="raise_on_sql",
|
56
|
+
foreign_keys="GalaxyCluster.orgc_id",
|
57
|
+
) # type:ignore[assignment,var-annotated]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from sqlalchemy import Boolean, Integer, String
|
2
|
+
from sqlalchemy.orm import relationship
|
2
3
|
|
3
4
|
from mmisp.db.database import Base
|
4
5
|
from mmisp.db.mypy import Mapped, mapped_column
|
@@ -18,3 +19,6 @@ class Tag(Base):
|
|
18
19
|
is_galaxy: Mapped[bool] = mapped_column(Boolean, default=False)
|
19
20
|
is_custom_galaxy: Mapped[bool] = mapped_column(Boolean, default=False)
|
20
21
|
local_only: Mapped[bool] = mapped_column(Boolean, default=False)
|
22
|
+
|
23
|
+
attributetags = relationship("AttributeTag", back_populates="tag", lazy="raise_on_sql", viewonly=True)
|
24
|
+
eventtags = relationship("EventTag", back_populates="tag", lazy="raise_on_sql", viewonly=True)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from time import time
|
2
2
|
|
3
3
|
from sqlalchemy import BigInteger, Boolean, DateTime, ForeignKey, Integer, String, Text
|
4
|
+
from sqlalchemy.orm import relationship
|
4
5
|
|
5
6
|
from mmisp.db.mypy import Mapped, mapped_column
|
6
7
|
|
@@ -44,3 +45,6 @@ class User(Base):
|
|
44
45
|
totp: Mapped[str] = mapped_column(String(255))
|
45
46
|
hotp_counter: Mapped[int] = mapped_column(Integer)
|
46
47
|
last_pw_change: Mapped[int] = mapped_column(BigInteger)
|
48
|
+
|
49
|
+
# Relationships
|
50
|
+
org = relationship("Organisation", back_populates="users", lazy="raise_on_sql")
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from sqlalchemy import and_
|
4
|
+
|
5
|
+
from mmisp.db.models.attribute import Attribute
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from sqlalchemy import ColumnExpressionArgument
|
9
|
+
else:
|
10
|
+
ColumnExpressionArgument = any
|
11
|
+
|
12
|
+
|
13
|
+
def get_search_filters(
|
14
|
+
value: str | None = None,
|
15
|
+
value1: str | None = None,
|
16
|
+
value2: str | None = None,
|
17
|
+
type: str | None = None,
|
18
|
+
category: str | None = None,
|
19
|
+
org: str | None = None,
|
20
|
+
tags: list[str] | None = None,
|
21
|
+
from_: str | None = None,
|
22
|
+
to: str | None = None,
|
23
|
+
last: int | None = None,
|
24
|
+
eventid: str | None = None,
|
25
|
+
published: bool | None = None,
|
26
|
+
to_ids: bool | None = None,
|
27
|
+
deleted: bool | None = None,
|
28
|
+
**kwargs,
|
29
|
+
) -> ColumnExpressionArgument:
|
30
|
+
cond = [True] # for empty filters
|
31
|
+
if value is not None:
|
32
|
+
cond.append(Attribute.value == value)
|
33
|
+
if value1 is not None:
|
34
|
+
cond.append(Attribute.value1 == value1)
|
35
|
+
if value2 is not None:
|
36
|
+
cond.append(Attribute.value2 == value2)
|
37
|
+
if type is not None:
|
38
|
+
cond.append(Attribute.type == type)
|
39
|
+
if category is not None:
|
40
|
+
cond.append(Attribute.category == category)
|
41
|
+
if org is not None:
|
42
|
+
raise NotImplementedError("filtering by org is currently not implemented")
|
43
|
+
if tags is not None:
|
44
|
+
raise NotImplementedError("filtering by tags is currently not implemented")
|
45
|
+
if from_ is not None:
|
46
|
+
raise NotImplementedError("filtering by from is currently not implemented")
|
47
|
+
if to is not None:
|
48
|
+
raise NotImplementedError("filtering by to is currently not implemented")
|
49
|
+
if last is not None:
|
50
|
+
raise NotImplementedError("filtering by last is currently not implemented")
|
51
|
+
if eventid is not None:
|
52
|
+
raise NotImplementedError("filtering by eventid is currently not implemented")
|
53
|
+
if published is not None:
|
54
|
+
raise NotImplementedError("filtering by published is currently not implemented")
|
55
|
+
if to_ids is not None:
|
56
|
+
cond.append(Attribute.to_ids == to_ids)
|
57
|
+
if deleted is not None:
|
58
|
+
cond.append(Attribute.deleted == deleted)
|
59
|
+
|
60
|
+
return and_(*cond)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import httpx
|
2
|
+
from deepdiff import DeepDiff
|
3
|
+
from icecream import ic
|
4
|
+
|
5
|
+
|
6
|
+
def to_legacy_format(data):
|
7
|
+
if isinstance(data, bool):
|
8
|
+
return data
|
9
|
+
elif isinstance(data, (int, float)):
|
10
|
+
return str(data)
|
11
|
+
elif isinstance(data, dict):
|
12
|
+
return {key: to_legacy_format(value) for key, value in data.items()}
|
13
|
+
elif isinstance(data, list):
|
14
|
+
return [to_legacy_format(x) for x in data]
|
15
|
+
return data
|
16
|
+
|
17
|
+
|
18
|
+
def get_legacy_modern_diff(http_method, path, body, auth_key, client):
|
19
|
+
clear_key, auth_key = auth_key
|
20
|
+
headers = {"authorization": clear_key, "accept": "application/json"}
|
21
|
+
|
22
|
+
ic("-" * 50)
|
23
|
+
ic(f"Calling {path}")
|
24
|
+
ic(body)
|
25
|
+
|
26
|
+
kwargs = {"headers": headers}
|
27
|
+
if http_method != "get":
|
28
|
+
kwargs["json"] = body
|
29
|
+
|
30
|
+
call = getattr(client, http_method)
|
31
|
+
response = call(path, **kwargs)
|
32
|
+
response_json = response.json()
|
33
|
+
|
34
|
+
call = getattr(httpx, http_method)
|
35
|
+
legacy_response = call(f"http://misp-core{path}", **kwargs)
|
36
|
+
ic(legacy_response)
|
37
|
+
legacy_response_json = legacy_response.json()
|
38
|
+
ic("Modern MISP Response")
|
39
|
+
ic(response_json)
|
40
|
+
ic("Legacy MISP Response")
|
41
|
+
ic(legacy_response_json)
|
42
|
+
|
43
|
+
diff = DeepDiff(to_legacy_format(response_json), to_legacy_format(legacy_response_json), verbose_level=2)
|
44
|
+
ic(diff)
|
45
|
+
|
46
|
+
# remove None values added in Modern MISP.
|
47
|
+
# They shouldnt hurt and removing all None
|
48
|
+
# overshoots, MISP is inconsistent when to include what.
|
49
|
+
# Note: We don't want the opposite. If MISP includes None, Modern MISP should do this as well!
|
50
|
+
diff["dictionary_item_removed"] = {
|
51
|
+
k: v for k, v in diff["dictionary_item_removed"].items() if v is not None and v != [] and v != {}
|
52
|
+
}
|
53
|
+
if diff["dictionary_item_removed"] == {}:
|
54
|
+
del diff["dictionary_item_removed"]
|
55
|
+
|
56
|
+
return diff
|