mmisp-lib 0.8.1__tar.gz → 0.8.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/PKG-INFO +2 -1
  2. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/pyproject.toml +2 -1
  3. mmisp_lib-0.8.3/src/mmisp/api_schemas/object_templates.py +50 -0
  4. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/organisations.py +5 -5
  5. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/sharing_groups.py +51 -1
  6. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/commandline_tool/main.py +2 -2
  7. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/commandline_tool/organisation.py +3 -3
  8. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/database.py +5 -0
  9. mmisp_lib-0.8.3/src/mmisp/db/list_json_type.py +31 -0
  10. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/mixins.py +2 -0
  11. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/attribute.py +4 -4
  12. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/auth_key.py +3 -3
  13. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/event.py +1 -1
  14. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/feed.py +3 -3
  15. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/galaxy.py +1 -1
  16. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/galaxy_cluster.py +4 -21
  17. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/identity_provider.py +1 -1
  18. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/object.py +39 -6
  19. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/organisation.py +2 -1
  20. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/server.py +7 -6
  21. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/sharing_group.py +44 -1
  22. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/tag.py +1 -1
  23. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/user.py +7 -7
  24. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/mypy.py +6 -1
  25. mmisp_lib-0.8.3/src/mmisp/db/object_json_type.py +34 -0
  26. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/compatibility_helpers.py +13 -0
  27. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/fixtures.py +214 -234
  28. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/organisation_generator.py +1 -1
  29. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp_lib.egg-info/PKG-INFO +2 -1
  30. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp_lib.egg-info/SOURCES.txt +3 -0
  31. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp_lib.egg-info/requires.txt +1 -0
  32. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/tests/test_commandline_tool.py +3 -3
  33. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/LICENSE +0 -0
  34. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/README.md +0 -0
  35. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/setup.cfg +0 -0
  36. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/__init__.py +0 -0
  37. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/attributes.py +0 -0
  38. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/auth_keys.py +0 -0
  39. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/authentication.py +0 -0
  40. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/common.py +0 -0
  41. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/events.py +0 -0
  42. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/feeds.py +0 -0
  43. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/galaxies.py +0 -0
  44. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/galaxy_clusters.py +0 -0
  45. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/galaxy_common.py +0 -0
  46. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/jobs.py +0 -0
  47. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/logs.py +0 -0
  48. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/noticelists.py +0 -0
  49. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/objects.py +0 -0
  50. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/py.typed +0 -0
  51. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/responses/__init__.py +0 -0
  52. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/responses/check_graph_response.py +0 -0
  53. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/responses/standard_status_response.py +0 -0
  54. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/roles.py +0 -0
  55. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/server.py +0 -0
  56. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/servers.py +0 -0
  57. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/shadow_attribute.py +0 -0
  58. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/sightings.py +0 -0
  59. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/statistics.py +0 -0
  60. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/tags.py +0 -0
  61. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/taxonomies.py +0 -0
  62. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/user_settings.py +0 -0
  63. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/users.py +0 -0
  64. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/warninglists.py +0 -0
  65. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/api_schemas/workflows.py +0 -0
  66. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/commandline_tool/__init__.py +0 -0
  67. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/commandline_tool/py.typed +0 -0
  68. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/commandline_tool/setup.py +0 -0
  69. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/commandline_tool/user.py +0 -0
  70. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/__init__.py +0 -0
  71. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/additional_properties.py +0 -0
  72. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/all_models.py +0 -0
  73. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/config.py +0 -0
  74. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/lib.py +0 -0
  75. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/__init__.py +0 -0
  76. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/admin_setting.py +0 -0
  77. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/blocklist.py +0 -0
  78. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/correlation.py +0 -0
  79. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/log.py +0 -0
  80. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/noticelist.py +0 -0
  81. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/post.py +0 -0
  82. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/role.py +0 -0
  83. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/shadow_attribute.py +0 -0
  84. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/sighting.py +0 -0
  85. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/taxonomy.py +0 -0
  86. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/threat_level.py +0 -0
  87. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/user_setting.py +0 -0
  88. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/warninglist.py +0 -0
  89. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/workflow.py +0 -0
  90. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/models/workflow_blueprint.py +0 -0
  91. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/print_changes.py +0 -0
  92. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/py.typed +0 -0
  93. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/db/uuid_type.py +0 -0
  94. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/__init__.py +0 -0
  95. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/actions.py +0 -0
  96. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/attribute_search_filter.py +0 -0
  97. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/attributes.py +0 -0
  98. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/distribution.py +0 -0
  99. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/fallbacks.py +0 -0
  100. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/galaxies.py +0 -0
  101. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/galaxy_clusters.py +0 -0
  102. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/logger.py +0 -0
  103. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/permissions.py +0 -0
  104. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/py.typed +0 -0
  105. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/serialisation_helper.py +0 -0
  106. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/lib/uuid.py +0 -0
  107. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/__init__.py +0 -0
  108. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/enrichment/__init__.py +0 -0
  109. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/enrichment/data.py +0 -0
  110. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/enrichment/enrichment_plugin.py +0 -0
  111. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/exceptions.py +0 -0
  112. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/models/__init__.py +0 -0
  113. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/models/attribute.py +0 -0
  114. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/plugin_info.py +0 -0
  115. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/plugin_type.py +0 -0
  116. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/plugins/py.typed +0 -0
  117. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/__init__.py +0 -0
  118. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/attribute_generator.py +0 -0
  119. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/feed_generator.py +0 -0
  120. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/attribute_generator.py +0 -0
  121. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/auth_key_generator.py +0 -0
  122. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/correlation_exclusions_generator.py +0 -0
  123. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/correlation_value_generator.py +0 -0
  124. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/default_correlation_generator.py +0 -0
  125. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/event_generator.py +0 -0
  126. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/galaxy_generator.py +0 -0
  127. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/identity_provider_generator.py +0 -0
  128. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/noticelist_generator.py +0 -0
  129. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/object_generator.py +0 -0
  130. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/over_correlating_value_generator.py +0 -0
  131. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/post_generator.py +0 -0
  132. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/role_generator.py +0 -0
  133. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/server_generator.py +0 -0
  134. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/shadow_attribute_generator.py +0 -0
  135. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/sharing_group_generator.py +0 -0
  136. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/sighting_generator.py +0 -0
  137. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/tag_generator.py +0 -0
  138. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/taxonomy_generator.py +0 -0
  139. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/user_generator.py +0 -0
  140. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/user_setting_generator.py +0 -0
  141. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/warninglist_generator.py +0 -0
  142. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/model_generators/workflow_generator.py +0 -0
  143. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/object_generator.py +0 -0
  144. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/sighting_generator.py +0 -0
  145. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/tag_generator.py +0 -0
  146. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/tests/generators/taxonomies_generator.py +0 -0
  147. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/util/__init__.py +0 -0
  148. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/util/crypto.py +0 -0
  149. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/util/models.py +0 -0
  150. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/util/partial.py +0 -0
  151. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/util/py.typed +0 -0
  152. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/util/uuid.py +0 -0
  153. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/__init__.py +0 -0
  154. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/execution.py +0 -0
  155. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/fastapi.py +0 -0
  156. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/graph.py +0 -0
  157. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/input.py +0 -0
  158. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/legacy.py +0 -0
  159. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/misp_core_format.py +0 -0
  160. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/modules.py +0 -0
  161. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp/workflows/py.typed +0 -0
  162. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp_lib.egg-info/dependency_links.txt +0 -0
  163. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp_lib.egg-info/entry_points.txt +0 -0
  164. {mmisp_lib-0.8.1 → mmisp_lib-0.8.3}/src/mmisp_lib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mmisp-lib
3
- Version: 0.8.1
3
+ Version: 0.8.3
4
4
  Requires-Python: >=3.11.0
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE
@@ -21,6 +21,7 @@ Requires-Dist: nanoid==2.0.0
21
21
  Requires-Dist: cryptography==42.0.5
22
22
  Requires-Dist: jinja2~=3.1.4
23
23
  Requires-Dist: fire
24
+ Requires-Dist: packaging
24
25
  Provides-Extra: dev
25
26
  Requires-Dist: ruff>=0.3.7; extra == "dev"
26
27
  Requires-Dist: mypy==1.8.0; extra == "dev"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mmisp-lib"
3
- version = "0.8.1"
3
+ version = "0.8.3"
4
4
  description = ""
5
5
  authors = []
6
6
  readme = "README.md"
@@ -25,6 +25,7 @@ dependencies = [
25
25
  "cryptography==42.0.5",
26
26
  "jinja2~=3.1.4",
27
27
  "fire",
28
+ "packaging",
28
29
  ]
29
30
 
30
31
 
@@ -0,0 +1,50 @@
1
+ from pydantic import BaseModel, Field
2
+ from pydantic.types import UUID
3
+
4
+
5
+ class ObjectTemplatesRequirements(BaseModel):
6
+ requiredOneOf: list[str] | None
7
+ required: list[str] | None
8
+
9
+
10
+ class ObjectTemplate(BaseModel):
11
+ class Config:
12
+ allow_population_by_field_name = True
13
+
14
+ id: int
15
+ user_id: int
16
+ org_id: int
17
+ uuid: UUID
18
+ name: str
19
+ meta_category: str = Field(..., alias="meta-category")
20
+ description: str
21
+ version: str
22
+ requirements: ObjectTemplatesRequirements
23
+ fixed: bool
24
+ active: bool
25
+
26
+
27
+ class ObjectTemplateElement(BaseModel):
28
+ class Config:
29
+ allow_population_by_field_name = True
30
+
31
+ id: int
32
+ object_template_id: int
33
+ object_relation: str
34
+ type: str # AttributeType?
35
+ ui_priority: int = Field(..., alias="ui-priority")
36
+ categories: list
37
+ sane_default: list
38
+ values_list: list
39
+ description: str
40
+ disable_correlation: bool | None
41
+ multiple: bool
42
+
43
+
44
+ class RespObjectTemplateView(BaseModel):
45
+ ObjectTemplate: ObjectTemplate
46
+ ObjectTemplateElement: list[ObjectTemplateElement]
47
+
48
+
49
+ class RespItemObjectTemplateIndex(BaseModel):
50
+ ObjectTemplate: ObjectTemplate
@@ -23,7 +23,7 @@ class Organisation(BaseOrganisation):
23
23
  contacts: str | None = None
24
24
  local: bool
25
25
  """organisation gains access to the local instance, otherwise treated as external"""
26
- restricted_to_domain: str | list | None = None
26
+ restricted_to_domain: list | str | None = None
27
27
  landingpage: str | None = None
28
28
 
29
29
  class Config:
@@ -45,7 +45,7 @@ class GetOrganisationResponse(BaseModel):
45
45
  created_by: str
46
46
  contacts: str | None = None
47
47
  local: bool
48
- restricted_to_domain: str | list | None = None
48
+ restricted_to_domain: list | str | None = None
49
49
  landingpage: str | None = None
50
50
 
51
51
  def dict(self: Self, *args, **kwargs) -> dict:
@@ -90,7 +90,7 @@ class OrganisationUsersResponse(BaseModel):
90
90
  uuid: str | None = None
91
91
  contacts: str | None = None
92
92
  local: bool | None = None
93
- restricted_to_domain: str | list | None = None
93
+ restricted_to_domain: list | str | None = None
94
94
  landingpage: str | None = None
95
95
 
96
96
 
@@ -105,7 +105,7 @@ class AddOrganisation(BaseModel):
105
105
  contacts: str | None = None
106
106
  local: bool
107
107
  """organisation gains access to the local instance, otherwise treated as external"""
108
- restricted_to_domain: str | None = None
108
+ restricted_to_domain: list[str] | None = None
109
109
  landingpage: str | None = None
110
110
 
111
111
  class Config:
@@ -121,7 +121,7 @@ class EditOrganisation(BaseModel):
121
121
  contacts: str | None = None
122
122
  local: bool
123
123
  """organisation gains access to the local instance, otherwise treated as external"""
124
- restricted_to_domain: str | None = None
124
+ restricted_to_domain: list[str] | None = None
125
125
  landingpage: str | None = None
126
126
 
127
127
  class Config:
@@ -1,3 +1,4 @@
1
+ import uuid
1
2
  from datetime import datetime
2
3
 
3
4
  from pydantic import BaseModel, Field
@@ -22,6 +23,28 @@ class SharingGroup(BaseModel):
22
23
  roaming: bool
23
24
 
24
25
 
26
+ # org_count: int = 0
27
+
28
+
29
+ class ShortSharingGroup(BaseModel):
30
+ id: int
31
+ name: str
32
+ releasability: str
33
+ description: str
34
+ uuid: str
35
+ active: bool
36
+ local: bool
37
+ roaming: bool
38
+
39
+ org_count: int = 0
40
+
41
+
42
+ class ShortOrganisation(BaseModel):
43
+ id: int
44
+ name: str
45
+ uuid: uuid.UUID
46
+
47
+
25
48
  class SharingGroupServer(BaseModel):
26
49
  id: int
27
50
  sharing_group_id: int
@@ -81,12 +104,39 @@ class ViewUpdateSharingGroupLegacyResponseSharingGroupOrgItem(BaseModel):
81
104
  Organisation: ViewUpdateSharingGroupLegacyResponseOrganisationInfo
82
105
 
83
106
 
84
- class ViewUpdateSharingGroupLegacyResponse(BaseModel):
107
+ class SharingGroupResponse(BaseModel):
108
+ SharingGroup: ShortSharingGroup
109
+ Organisation: ShortOrganisation
110
+ SharingGroupOrg: list[ViewUpdateSharingGroupLegacyResponseSharingGroupOrgItem]
111
+ SharingGroupServer: list[ViewUpdateSharingGroupLegacyResponseSharingGroupServerItem]
112
+
113
+ editable: bool | None = None
114
+ deletable: bool | None = None
115
+
116
+ class Config:
117
+ json_encoders = {datetime: lambda v: v.strftime("%Y-%m-%d %H:%M:%S")}
118
+
119
+
120
+ class SingleSharingGroupResponse(BaseModel):
85
121
  SharingGroup: SharingGroup
86
122
  Organisation: Organisation
87
123
  SharingGroupOrg: list[ViewUpdateSharingGroupLegacyResponseSharingGroupOrgItem]
88
124
  SharingGroupServer: list[ViewUpdateSharingGroupLegacyResponseSharingGroupServerItem]
89
125
 
126
+ class Config:
127
+ json_encoders = {datetime: lambda v: v.strftime("%Y-%m-%d %H:%M:%S")}
128
+
129
+
130
+ class ViewUpdateSharingGroupLegacyResponse(SharingGroupResponse):
131
+ pass
132
+
133
+
134
+ class GetSharingGroupsIndex(BaseModel):
135
+ response: list[SharingGroupResponse]
136
+
137
+ class Config:
138
+ json_encoders = {datetime: lambda v: v.strftime("%Y-%m-%d %H:%M:%S")}
139
+
90
140
 
91
141
  class UpdateSharingGroupLegacyBody(BaseModel):
92
142
  id: int | None = None
@@ -43,7 +43,7 @@ async def create_organisation(
43
43
  sector: str | None = None,
44
44
  contacts_email: str | None = None,
45
45
  local: bool | None = None,
46
- restricted_domain: str | None = None,
46
+ restricted_domain: list[str] | None = None,
47
47
  landingpage: str | None = None,
48
48
  ) -> str:
49
49
  """create-organisation <name> [-admin_email <admin_email>] [- description <description>] [-type <type>]
@@ -115,7 +115,7 @@ async def edit_organisation(
115
115
  sector: str | None = None,
116
116
  contacts_email: str | None = None,
117
117
  local: bool | None = None,
118
- restricted_domain: str | None = None,
118
+ restricted_domain: list[str] | None = None,
119
119
  landingpage: str | None = None,
120
120
  ) -> str:
121
121
  """edit-organisation <organisation> [-new_name <new_name>] [-admin_email <admin_email>] [-description <description>]
@@ -18,7 +18,7 @@ async def create(
18
18
  sector: str | None,
19
19
  contacts_email: str | None,
20
20
  local: bool | None,
21
- restricted_domain: str | None,
21
+ restricted_domain: list[str] | None,
22
22
  landingpage: str | None,
23
23
  ) -> None:
24
24
  organisation = Organisation()
@@ -67,7 +67,7 @@ async def edit_organisation(
67
67
  sector: str | None,
68
68
  contacts_email: str | None,
69
69
  local: bool | None,
70
- restricted_domain: str | None,
70
+ restricted_domain: list[str] | None,
71
71
  landingpage: str | None,
72
72
  ) -> None:
73
73
  if isinstance(organisation, str):
@@ -109,7 +109,7 @@ async def set_attributes(
109
109
  sector: str | None,
110
110
  contacts_email: str | None,
111
111
  local: bool | None,
112
- restricted_domain: str | None,
112
+ restricted_domain: list[str] | None,
113
113
  landingpage: str | None,
114
114
  ) -> None:
115
115
  if name is not None:
@@ -1,6 +1,7 @@
1
1
  import contextlib
2
2
  import time
3
3
  from collections.abc import AsyncIterator
4
+ from contextvars import ContextVar
4
5
  from typing import Self, TypeAlias
5
6
 
6
7
  from sqlalchemy.engine.url import make_url
@@ -20,6 +21,8 @@ Base = declarative_base()
20
21
 
21
22
  _no_database: str = "DatabaseSessionManager is not initialized"
22
23
 
24
+ dry_run: ContextVar[bool] = ContextVar("dry_run", default=False)
25
+
23
26
 
24
27
  class DatabaseSessionManager:
25
28
  def __init__(self: Self, db_url: str = config.DATABASE_URL) -> None:
@@ -108,6 +111,8 @@ class DatabaseSessionManager:
108
111
  async def get_db() -> AsyncIterator[Session]:
109
112
  async with sessionmanager.session() as session:
110
113
  yield session
114
+ if dry_run.get():
115
+ await session.rollback()
111
116
 
112
117
 
113
118
  async def create_all_models() -> None:
@@ -0,0 +1,31 @@
1
+ import json
2
+ from typing import Any, Self
3
+
4
+ from sqlalchemy.engine import Dialect
5
+ from sqlalchemy.types import Text, TypeDecorator
6
+
7
+
8
+ class DBListJson(TypeDecorator):
9
+ impl = Text
10
+
11
+ def load_dialect_impl(self: Self, dialect: Dialect) -> Any:
12
+ return dialect.type_descriptor(Text)
13
+
14
+ def process_bind_param(self: Self, value: Any, dialect: Dialect) -> str | None:
15
+ """Handle value before getting into the DB"""
16
+ if value is None:
17
+ return None
18
+ if not isinstance(value, list):
19
+ raise ValueError("this type should only be used for lists")
20
+ return json.dumps(value)
21
+
22
+ def process_result_value(self: Self, value: Any, dialect: Dialect) -> list | None:
23
+ """Handle values from the database"""
24
+ if value is None:
25
+ return None
26
+
27
+ res = json.loads(value)
28
+ if not isinstance(res, list):
29
+ raise ValueError("this type should only be used for lists")
30
+
31
+ return res
@@ -18,6 +18,8 @@ class DictMixin:
18
18
  if omit is None:
19
19
  omit = set()
20
20
 
21
+ print(self.__mapper__.c.keys())
22
+
21
23
  unloaded = inspect(self).unloaded
22
24
  d = {}
23
25
  for key in self.__mapper__.c.keys(): # type:ignore[attr-defined]
@@ -40,7 +40,7 @@ class Attribute(Base, DictMixin):
40
40
  Integer, ForeignKey("events.id", ondelete="CASCADE"), nullable=False, index=True
41
41
  )
42
42
  object_id: Mapped[int] = mapped_column(Integer, nullable=False, default=0, index=True)
43
- object_relation: Mapped[str] = mapped_column(String(255), index=True)
43
+ object_relation: Mapped[str | None] = mapped_column(String(255), index=True)
44
44
  category: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
45
45
  type: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
46
46
  value1: Mapped[str] = mapped_column(Text, nullable=False)
@@ -49,11 +49,11 @@ class Attribute(Base, DictMixin):
49
49
  timestamp: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
50
50
  distribution: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
51
51
  sharing_group_id: Mapped[int] = mapped_column(Integer, index=True, default=0)
52
- comment: Mapped[str] = mapped_column(Text)
52
+ comment: Mapped[str | None] = mapped_column(Text)
53
53
  deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
54
54
  disable_correlation: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
55
- first_seen: Mapped[int] = mapped_column(BigInteger, index=True)
56
- last_seen: Mapped[int] = mapped_column(BigInteger, index=True)
55
+ first_seen: Mapped[int | None] = mapped_column(BigInteger, index=True)
56
+ last_seen: Mapped[int | None] = mapped_column(BigInteger, index=True)
57
57
 
58
58
  event = relationship("Event", back_populates="attributes", lazy="joined") # type:ignore[var-annotated]
59
59
  mispobject = relationship(
@@ -19,7 +19,7 @@ class AuthKey(Base):
19
19
  created: Mapped[int] = mapped_column(Integer, nullable=False, default=time)
20
20
  expiration: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
21
21
  read_only: Mapped[bool] = mapped_column(Boolean, nullable=False, default=0)
22
- comment: Mapped[str] = mapped_column(String(255))
23
- allowed_ips: Mapped[str] = mapped_column(String(255))
24
- unique_ips: Mapped[str] = mapped_column(String(255))
22
+ comment: Mapped[str | None] = mapped_column(String(255))
23
+ allowed_ips: Mapped[str | None] = mapped_column(String(255))
24
+ unique_ips: Mapped[str | None] = mapped_column(String(255))
25
25
  user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), nullable=False)
@@ -37,7 +37,7 @@ class Event(Base):
37
37
  sighting_timestamp: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
38
38
  disable_correlation: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
39
39
  extends_uuid: Mapped[str] = mapped_column(String(40), default="", index=True)
40
- protected: Mapped[bool] = mapped_column(Boolean)
40
+ protected: Mapped[bool] = mapped_column(Boolean, default=False)
41
41
 
42
42
  attributes = relationship("Attribute", back_populates="event") # type:ignore[assignment,var-annotated]
43
43
  mispobjects = relationship("Object", back_populates="event") # type:ignore[assignment,var-annotated]
@@ -11,7 +11,7 @@ class Feed(Base):
11
11
  name: Mapped[str] = mapped_column(String(255), nullable=False)
12
12
  provider: Mapped[str] = mapped_column(String(255), nullable=False)
13
13
  url: Mapped[str] = mapped_column(String(255), nullable=False)
14
- rules: Mapped[str] = mapped_column(Text, default=None)
14
+ rules: Mapped[str | None] = mapped_column(Text, default=None)
15
15
  enabled: Mapped[bool] = mapped_column(Boolean, default=False)
16
16
  distribution: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
17
17
  sharing_group_id: Mapped[int] = mapped_column(Integer, nullable=False, default=0, index=True)
@@ -23,11 +23,11 @@ class Feed(Base):
23
23
  event_id: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
24
24
  publish: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
25
25
  override_ids: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
26
- settings: Mapped[str] = mapped_column(Text)
26
+ settings: Mapped[str | None] = mapped_column(Text)
27
27
  input_source: Mapped[str] = mapped_column(String(255), nullable=False, default="network", index=True)
28
28
  delete_local_file: Mapped[bool] = mapped_column(Boolean, default=False)
29
29
  lookup_visible: Mapped[bool] = mapped_column(Boolean, default=False)
30
- headers: Mapped[str] = mapped_column(Text)
30
+ headers: Mapped[str | None] = mapped_column(Text)
31
31
  caching_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
32
32
  force_to_ids: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
33
33
  orgc_id: Mapped[int] = mapped_column(Integer, nullable=False, default=0, index=True)
@@ -21,7 +21,7 @@ class Galaxy(Base, DictMixin, UpdateMixin):
21
21
  version: Mapped[str] = mapped_column(String(255), nullable=False)
22
22
  icon: Mapped[str] = mapped_column(String(255), nullable=False, default="")
23
23
  namespace: Mapped[str] = mapped_column(String(255), nullable=False, default="misp", index=True)
24
- kill_chain_order: Mapped[str] = mapped_column(String(255))
24
+ kill_chain_order: Mapped[str | None] = mapped_column(String(255))
25
25
  """must be serialized"""
26
26
  enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
27
27
  local_only: Mapped[bool] = mapped_column(Boolean, default=False)
@@ -1,10 +1,7 @@
1
- import json
2
- from typing import Self
3
-
4
1
  from sqlalchemy import Boolean, ForeignKey, Integer, String, Text
5
- from sqlalchemy.ext.hybrid import hybrid_property
6
2
  from sqlalchemy.orm import relationship
7
3
 
4
+ from mmisp.db.list_json_type import DBListJson
8
5
  from mmisp.db.mixins import DictMixin, UpdateMixin
9
6
  from mmisp.db.mypy import Mapped, mapped_column
10
7
  from mmisp.db.uuid_type import DBUUID
@@ -28,7 +25,7 @@ class GalaxyCluster(Base, UpdateMixin, DictMixin):
28
25
  Integer, ForeignKey(Galaxy.id, ondelete="CASCADE"), nullable=False, index=True
29
26
  )
30
27
  source: Mapped[str] = mapped_column(String(255), nullable=False, default="")
31
- _authors: Mapped[str] = mapped_column("authors", Text, nullable=False)
28
+ authors: Mapped[list[str]] = mapped_column(DBListJson, nullable=False)
32
29
  version: Mapped[int] = mapped_column(Integer, default=0, index=True)
33
30
  distribution: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
34
31
  sharing_group_id: Mapped[int] = mapped_column(Integer, index=True, nullable=True, default=None)
@@ -36,8 +33,8 @@ class GalaxyCluster(Base, UpdateMixin, DictMixin):
36
33
  orgc_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True, default=0)
37
34
  default: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, index=True)
38
35
  locked: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
39
- extends_uuid: Mapped[str] = mapped_column(String(40), index=True)
40
- extends_version: Mapped[int] = mapped_column(Integer, index=True, nullable=True, default=None)
36
+ extends_uuid: Mapped[str | None] = mapped_column(String(40), index=True)
37
+ extends_version: Mapped[int | None] = mapped_column(Integer, index=True, nullable=True, default=None)
41
38
  published: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
42
39
  deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
43
40
 
@@ -75,20 +72,6 @@ class GalaxyCluster(Base, UpdateMixin, DictMixin):
75
72
  uselist=False,
76
73
  ) # type:ignore[assignment,var-annotated]
77
74
 
78
- def __init__(self: Self, *arg, **kwargs) -> None:
79
- if "authors" in kwargs:
80
- self._authors = json.dumps(kwargs["authors"])
81
- del kwargs["authors"]
82
- super().__init__(*arg, **kwargs)
83
-
84
- @hybrid_property
85
- def authors(self: Self) -> list[str]:
86
- return json.loads(self._authors)
87
-
88
- @authors.setter # type: ignore[no-redef]
89
- def authors(self: Self, value: list[str]) -> None:
90
- self._authors = json.dumps(value)
91
-
92
75
 
93
76
  class GalaxyElement(Base, DictMixin, UpdateMixin):
94
77
  __tablename__ = "galaxy_elements"
@@ -17,7 +17,7 @@ class OIDCIdentityProvider(Base):
17
17
  base_url: Mapped[str] = mapped_column(String(255), nullable=False)
18
18
  client_id: Mapped[str] = mapped_column(String(255), nullable=False)
19
19
  client_secret: Mapped[str] = mapped_column(String(255), nullable=False)
20
- scope: Mapped[str] = mapped_column(String(255))
20
+ scope: Mapped[str] = mapped_column(String(255), default="openid")
21
21
  """Possibility to add more scopes to be requested from the idp in addition to the default scopes,
22
22
  currently not used."""
23
23
  created: Mapped[DateTime] = mapped_column(DateTime, default=datetime.utcnow)
@@ -1,9 +1,13 @@
1
- from sqlalchemy import Boolean, ForeignKey, Integer, String
1
+ from typing import Optional
2
+
3
+ from sqlalchemy import Boolean, ForeignKey, Integer, String, Text
2
4
  from sqlalchemy.orm import relationship
3
5
 
4
6
  from mmisp.db.database import Base
7
+ from mmisp.db.list_json_type import DBListJson
5
8
  from mmisp.db.mixins import DictMixin
6
9
  from mmisp.db.mypy import Mapped, mapped_column
10
+ from mmisp.db.object_json_type import DBObjectJson
7
11
  from mmisp.lib.uuid import uuid
8
12
 
9
13
 
@@ -13,7 +17,7 @@ class Object(Base, DictMixin):
13
17
  id: Mapped[int] = mapped_column(Integer, primary_key=True, nullable=False)
14
18
  uuid: Mapped[str] = mapped_column(String(255), unique=True, default=uuid, index=True)
15
19
  name: Mapped[str] = mapped_column(String(255), index=True)
16
- meta_category: Mapped[str] = mapped_column("meta-category", String(255), index=True, key="meta_category")
20
+ meta_category: Mapped[str] = mapped_column("meta-category", String(255), index=True)
17
21
  description: Mapped[str] = mapped_column(String(255))
18
22
  template_uuid: Mapped[str] = mapped_column(String(255), index=True, default=None)
19
23
  template_version: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
@@ -44,12 +48,41 @@ class ObjectTemplate(Base, DictMixin):
44
48
  __tablename__ = "object_templates"
45
49
 
46
50
  id: Mapped[int] = mapped_column(Integer, primary_key=True, nullable=False)
47
- uuid: Mapped[str] = mapped_column(String(255), unique=True, default=uuid, index=True)
48
- name: Mapped[str] = mapped_column(String(255), index=True)
49
51
  user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), index=True, nullable=False)
50
52
  org_id: Mapped[int] = mapped_column(Integer, ForeignKey("organisations.id"), index=True, nullable=False)
51
- description: Mapped[str] = mapped_column(String(255))
53
+ uuid: Mapped[str] = mapped_column(String(255), unique=True, default=uuid, index=True)
54
+ name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True, index=True)
55
+ meta_category: Mapped[Optional[str]] = mapped_column(
56
+ "meta-category", String(255), nullable=True, index=True, key="meta_category"
57
+ )
58
+ description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
52
59
  version: Mapped[int] = mapped_column(Integer, nullable=False)
53
- requirements: Mapped[str] = mapped_column(String(255))
60
+ requirements: Mapped[dict | None] = mapped_column(DBObjectJson, nullable=True)
54
61
  fixed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
55
62
  active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
63
+
64
+ elements: Mapped[list["ObjectTemplateElement"]] = relationship(
65
+ "ObjectTemplateElement", back_populates="object_template", lazy="raise_on_sql"
66
+ )
67
+
68
+
69
+ class ObjectTemplateElement(Base, DictMixin):
70
+ __tablename__ = "object_template_elements"
71
+
72
+ id: Mapped[int] = mapped_column(Integer, primary_key=True, nullable=False)
73
+ object_template_id: Mapped[int] = mapped_column(
74
+ Integer, ForeignKey(ObjectTemplate.id, ondelete="CASCADE"), nullable=False, index=True
75
+ )
76
+ object_relation: Mapped[Optional[str]] = mapped_column(String(255), nullable=True, index=True)
77
+ type: Mapped[Optional[str]] = mapped_column(Text, nullable=True, index=True)
78
+ ui_priority: Mapped[int] = mapped_column("ui-priority", Integer, nullable=False, key="ui_priority")
79
+ categories: Mapped[list[str] | None] = mapped_column(DBListJson, nullable=True)
80
+ sane_default: Mapped[list[str] | None] = mapped_column(DBListJson, nullable=True)
81
+ values_list: Mapped[list[str] | None] = mapped_column(DBListJson, nullable=True)
82
+ description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
83
+ disable_correlation: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True)
84
+ multiple: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
85
+
86
+ object_template: Mapped[ObjectTemplate] = relationship(
87
+ ObjectTemplate, back_populates="elements", lazy="raise_on_sql"
88
+ )
@@ -3,6 +3,7 @@ from datetime import datetime
3
3
  from sqlalchemy import Boolean, DateTime, Integer, String, Text
4
4
  from sqlalchemy.orm import relationship
5
5
 
6
+ from mmisp.db.list_json_type import DBListJson
6
7
  from mmisp.db.mixins import DictMixin
7
8
  from mmisp.db.mypy import Mapped, mapped_column
8
9
 
@@ -26,7 +27,7 @@ class Organisation(Base, DictMixin):
26
27
  uuid: Mapped[str] = mapped_column(String(255), unique=True)
27
28
  contacts: Mapped[str] = mapped_column(Text)
28
29
  local: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
29
- restricted_to_domain: Mapped[str] = mapped_column(Text)
30
+ restricted_to_domain: Mapped[list[str]] = mapped_column(DBListJson)
30
31
  landingpage: Mapped[str] = mapped_column(Text)
31
32
 
32
33
  # Relationship to users
@@ -1,12 +1,13 @@
1
1
  from sqlalchemy import Boolean, Integer, String, Text
2
2
  from sqlalchemy.orm import relationship
3
3
 
4
+ from mmisp.db.mixins import DictMixin
4
5
  from mmisp.db.mypy import Mapped, mapped_column
5
6
 
6
7
  from ..database import Base
7
8
 
8
9
 
9
- class Server(Base):
10
+ class Server(Base, DictMixin):
10
11
  __tablename__ = "servers"
11
12
 
12
13
  id: Mapped[int] = mapped_column(Integer, primary_key=True, nullable=False)
@@ -21,17 +22,17 @@ class Server(Base):
21
22
  pull_galaxy_clusters: Mapped[bool] = mapped_column(Boolean, default=False)
22
23
  push_analyst_data: Mapped[bool] = mapped_column(Boolean, default=False)
23
24
  pull_analyst_data: Mapped[bool] = mapped_column(Boolean, default=False)
24
- last_pulled_id: Mapped[int] = mapped_column("lastpulledid", Integer)
25
- last_pushed_id: Mapped[int] = mapped_column("lastpushedid", Integer)
26
- organization: Mapped[str] = mapped_column(String(10), default=None)
25
+ last_pulled_id: Mapped[int] = mapped_column("lastpulledid", Integer, nullable=True)
26
+ last_pushed_id: Mapped[int] = mapped_column("lastpushedid", Integer, nullable=True)
27
+ organization: Mapped[str | None] = mapped_column(String(10), default=None)
27
28
  remote_org_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
28
29
  publish_without_email: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
29
30
  unpublish_event: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
30
31
  self_signed: Mapped[bool] = mapped_column(Boolean, nullable=False)
31
32
  pull_rules: Mapped[str] = mapped_column(Text, nullable=False)
32
33
  push_rules: Mapped[str] = mapped_column(Text, nullable=False)
33
- cert_file: Mapped[str] = mapped_column(String(255))
34
- client_cert_file: Mapped[str] = mapped_column(String(255))
34
+ cert_file: Mapped[str | None] = mapped_column(String(255))
35
+ client_cert_file: Mapped[str | None] = mapped_column(String(255))
35
36
  internal: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
36
37
  skip_proxy: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
37
38
  caching_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
@@ -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
@@ -18,7 +19,7 @@ class SharingGroup(Base, DictMixin):
18
19
  description = mapped_column(Text, nullable=False, default="")
19
20
  uuid = mapped_column(String(40), unique=True, default=uuid, nullable=False)
20
21
  organisation_uuid = mapped_column(String(40), nullable=False)
21
- org_id = mapped_column(Integer, nullable=False, index=True)
22
+ org_id = mapped_column(Integer, nullable=False, index=True) # the organisation that created the sharing group
22
23
  sync_user_id = mapped_column(Integer, nullable=False, default=0, index=True)
23
24
  active = mapped_column(Boolean, nullable=False, default=False)
24
25
  created = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
@@ -26,6 +27,34 @@ class SharingGroup(Base, DictMixin):
26
27
  local = mapped_column(Boolean, nullable=False, default=True)
27
28
  roaming = mapped_column(Boolean, default=False, nullable=False)
28
29
 
30
+ creator_org = relationship(
31
+ "Organisation",
32
+ primaryjoin="SharingGroup.org_id == Organisation.id",
33
+ lazy="raise_on_sql",
34
+ foreign_keys="SharingGroup.org_id",
35
+ ) # type:ignore[assignment,var-annotated]
36
+ organisations = relationship(
37
+ "Organisation",
38
+ primaryjoin="SharingGroup.id == SharingGroupOrg.sharing_group_id",
39
+ secondary="sharing_group_orgs",
40
+ secondaryjoin="SharingGroupOrg.org_id == Organisation.id",
41
+ lazy="raise_on_sql",
42
+ viewonly=True,
43
+ )
44
+
45
+ sharing_group_orgs = relationship(
46
+ "SharingGroupOrg",
47
+ primaryjoin="SharingGroup.id == SharingGroupOrg.sharing_group_id",
48
+ lazy="raise_on_sql",
49
+ foreign_keys="SharingGroupOrg.sharing_group_id",
50
+ ) # type:ignore[assignment,var-annotated]
51
+ sharing_group_servers = relationship(
52
+ "SharingGroupServer",
53
+ primaryjoin="SharingGroup.id == SharingGroupServer.sharing_group_id",
54
+ lazy="raise_on_sql",
55
+ foreign_keys="SharingGroupServer.sharing_group_id",
56
+ ) # type:ignore[assignment,var-annotated]
57
+
29
58
 
30
59
  class SharingGroupOrg(Base, DictMixin):
31
60
  __tablename__ = "sharing_group_orgs"
@@ -35,6 +64,13 @@ class SharingGroupOrg(Base, DictMixin):
35
64
  org_id = mapped_column(Integer, index=True, nullable=False)
36
65
  extend = mapped_column(Boolean, default=False, nullable=False)
37
66
 
67
+ organisation = relationship(
68
+ "Organisation",
69
+ primaryjoin="SharingGroupOrg.org_id == Organisation.id",
70
+ lazy="raise_on_sql",
71
+ foreign_keys="SharingGroupOrg.org_id",
72
+ ) # type:ignore[assignment,var-annotated]
73
+
38
74
 
39
75
  class SharingGroupServer(Base, DictMixin):
40
76
  __tablename__ = "sharing_group_servers"
@@ -43,3 +79,10 @@ class SharingGroupServer(Base, DictMixin):
43
79
  sharing_group_id = mapped_column(Integer, index=True, nullable=False)
44
80
  server_id = mapped_column(Integer, index=True, nullable=False)
45
81
  all_orgs = mapped_column(Boolean, index=True, nullable=False, default=False)
82
+
83
+ server = relationship(
84
+ "Server",
85
+ primaryjoin="SharingGroupServer.server_id == Server.id",
86
+ lazy="raise_on_sql",
87
+ foreign_keys="SharingGroupServer.server_id",
88
+ ) # type:ignore[assignment,var-annotated]