mmisp-lib 0.1.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.
Files changed (166) hide show
  1. mmisp_lib-0.1.0/PKG-INFO +77 -0
  2. mmisp_lib-0.1.0/README.md +47 -0
  3. mmisp_lib-0.1.0/pyproject.toml +50 -0
  4. mmisp_lib-0.1.0/setup.cfg +4 -0
  5. mmisp_lib-0.1.0/src/mmisp/api_schemas/__init__.py +0 -0
  6. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/__init__.py +0 -0
  7. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/add_attribute_body.py +34 -0
  8. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/add_attribute_response.py +33 -0
  9. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/add_remove_tag_attribute_response.py +13 -0
  10. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/delete_attribute_response.py +8 -0
  11. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/delete_selected_attribute_body.py +9 -0
  12. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/delete_selected_attribute_response.py +13 -0
  13. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/edit_attribute_body.py +24 -0
  14. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/edit_attributes_response.py +42 -0
  15. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/get_all_attributes_response.py +38 -0
  16. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/get_attribute_response.py +41 -0
  17. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/get_attribute_statistics_response.py +137 -0
  18. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/get_describe_types_response.py +29 -0
  19. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/restore_attribute_reponse.py +25 -0
  20. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/search_attributes_body.py +74 -0
  21. mmisp_lib-0.1.0/src/mmisp/api_schemas/attributes/search_attributes_response.py +52 -0
  22. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/__init__.py +0 -0
  23. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/add_auth_key_body.py +10 -0
  24. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/add_auth_key_response.py +20 -0
  25. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/edit_auth_key_body.py +8 -0
  26. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/edit_auth_key_response.py +24 -0
  27. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/search_auth_keys_body.py +17 -0
  28. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/search_get_all_auth_keys_users_response.py +28 -0
  29. mmisp_lib-0.1.0/src/mmisp/api_schemas/auth_keys/view_auth_key_response.py +24 -0
  30. mmisp_lib-0.1.0/src/mmisp/api_schemas/authentication/__init__.py +0 -0
  31. mmisp_lib-0.1.0/src/mmisp/api_schemas/authentication/exchange_token_login_body.py +5 -0
  32. mmisp_lib-0.1.0/src/mmisp/api_schemas/authentication/password_login_body.py +6 -0
  33. mmisp_lib-0.1.0/src/mmisp/api_schemas/authentication/start_login_body.py +5 -0
  34. mmisp_lib-0.1.0/src/mmisp/api_schemas/authentication/start_login_response.py +21 -0
  35. mmisp_lib-0.1.0/src/mmisp/api_schemas/authentication/token_response.py +5 -0
  36. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/FreeTextImportWorkerBody.py +17 -0
  37. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/__init__.py +0 -0
  38. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/add_attribute_via_free_text_import_event_body.py +12 -0
  39. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/add_attribute_via_free_text_import_event_response.py +14 -0
  40. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/add_edit_get_event_response.py +234 -0
  41. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/add_event_body.py +30 -0
  42. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/add_remove_tag_events_response.py +11 -0
  43. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/delete_event_response.py +14 -0
  44. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/edit_event_body.py +28 -0
  45. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/get_all_events_response.py +99 -0
  46. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/get_event_response.py +8 -0
  47. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/index_events_body.py +30 -0
  48. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/index_events_response.py +40 -0
  49. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/publish_event_response.py +13 -0
  50. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/search_events_body.py +43 -0
  51. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/search_events_response.py +10 -0
  52. mmisp_lib-0.1.0/src/mmisp/api_schemas/events/unpublish_event_response.py +13 -0
  53. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/__init__.py +0 -0
  54. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/cache_feed_response.py +12 -0
  55. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/create_feed_body.py +30 -0
  56. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/enable_disable_feed_response.py +10 -0
  57. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/fetch_feeds_response.py +8 -0
  58. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/get_feed_response.py +47 -0
  59. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/toggle_feed_body.py +8 -0
  60. mmisp_lib-0.1.0/src/mmisp/api_schemas/feeds/update_feed_body.py +30 -0
  61. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/__init__.py +0 -0
  62. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/attach_galaxy_cluster_body.py +12 -0
  63. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/attach_galaxy_cluster_response.py +10 -0
  64. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/delete_force_update_import_galaxy_response.py +12 -0
  65. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/export_galaxies_body.py +16 -0
  66. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/export_galaxies_response.py +44 -0
  67. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/galaxy_schema.py +18 -0
  68. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/get_all_search_galaxies_response.py +22 -0
  69. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/get_galaxy_response.py +37 -0
  70. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/import_galaxies_body.py +15 -0
  71. mmisp_lib-0.1.0/src/mmisp/api_schemas/galaxies/search_galaxies_body.py +22 -0
  72. mmisp_lib-0.1.0/src/mmisp/api_schemas/noticelists/__init__.py +0 -0
  73. mmisp_lib-0.1.0/src/mmisp/api_schemas/noticelists/get_all_noticelist_response.py +10 -0
  74. mmisp_lib-0.1.0/src/mmisp/api_schemas/noticelists/get_noticelist_response.py +38 -0
  75. mmisp_lib-0.1.0/src/mmisp/api_schemas/objects/__init__.py +0 -0
  76. mmisp_lib-0.1.0/src/mmisp/api_schemas/objects/create_object_body.py +19 -0
  77. mmisp_lib-0.1.0/src/mmisp/api_schemas/objects/get_object_response.py +50 -0
  78. mmisp_lib-0.1.0/src/mmisp/api_schemas/objects/search_objects_body.py +49 -0
  79. mmisp_lib-0.1.0/src/mmisp/api_schemas/organisations/__init__.py +0 -0
  80. mmisp_lib-0.1.0/src/mmisp/api_schemas/organisations/organisation.py +24 -0
  81. mmisp_lib-0.1.0/src/mmisp/api_schemas/roles/__init__.py +0 -0
  82. mmisp_lib-0.1.0/src/mmisp/api_schemas/roles/role.py +71 -0
  83. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/__init__.py +0 -0
  84. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/add_org_to_sharing_group_body.py +6 -0
  85. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/add_org_to_sharing_group_legacy_body.py +5 -0
  86. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/add_server_to_sharing_group_body.py +6 -0
  87. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/add_server_to_sharing_group_legacy_body.py +5 -0
  88. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/create_sharing_group_body.py +12 -0
  89. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/create_sharing_group_legacy_body.py +23 -0
  90. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/create_sharing_group_legacy_response.py +18 -0
  91. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/delete_sharing_group_legacy_response.py +5 -0
  92. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/get_all_sharing_groups_response.py +53 -0
  93. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/get_sharing_group_info_response.py +44 -0
  94. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/sharing_group.py +19 -0
  95. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/sharing_group_org.py +8 -0
  96. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/sharing_group_server.py +8 -0
  97. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/update_sharing_group_body.py +10 -0
  98. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/update_sharing_group_legacy_body.py +28 -0
  99. mmisp_lib-0.1.0/src/mmisp/api_schemas/sharing_groups/view_update_sharing_group_legacy_response.py +40 -0
  100. mmisp_lib-0.1.0/src/mmisp/api_schemas/sightings/__init__.py +0 -0
  101. mmisp_lib-0.1.0/src/mmisp/api_schemas/sightings/create_sighting_body.py +49 -0
  102. mmisp_lib-0.1.0/src/mmisp/api_schemas/sightings/get_sighting_response.py +27 -0
  103. mmisp_lib-0.1.0/src/mmisp/api_schemas/standard_status_response.py +13 -0
  104. mmisp_lib-0.1.0/src/mmisp/api_schemas/tags/__init__.py +0 -0
  105. mmisp_lib-0.1.0/src/mmisp/api_schemas/tags/create_tag_body.py +15 -0
  106. mmisp_lib-0.1.0/src/mmisp/api_schemas/tags/delete_tag_response.py +10 -0
  107. mmisp_lib-0.1.0/src/mmisp/api_schemas/tags/get_tag_response.py +31 -0
  108. mmisp_lib-0.1.0/src/mmisp/api_schemas/tags/search_tags_response.py +26 -0
  109. mmisp_lib-0.1.0/src/mmisp/api_schemas/tags/update_tag_body.py +15 -0
  110. mmisp_lib-0.1.0/src/mmisp/api_schemas/taxonomies/__init__.py +0 -0
  111. mmisp_lib-0.1.0/src/mmisp/api_schemas/taxonomies/export_taxonomies_response.py +30 -0
  112. mmisp_lib-0.1.0/src/mmisp/api_schemas/taxonomies/get_taxonomy_by_id_response.py +30 -0
  113. mmisp_lib-0.1.0/src/mmisp/api_schemas/taxonomies/get_taxonomy_response.py +21 -0
  114. mmisp_lib-0.1.0/src/mmisp/api_schemas/taxonomies/get_taxonomy_tags_response.py +32 -0
  115. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/__init__.py +0 -0
  116. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/get_uid_user_setting_response.py +21 -0
  117. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/get_user_settings_response.py +13 -0
  118. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/search_user_setting_body.py +7 -0
  119. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/search_user_setting_response.py +11 -0
  120. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/set_user_setting_body.py +5 -0
  121. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/set_user_setting_response.py +13 -0
  122. mmisp_lib-0.1.0/src/mmisp/api_schemas/user_settings/view_user_setting_response.py +13 -0
  123. mmisp_lib-0.1.0/src/mmisp/api_schemas/users/__init__.py +0 -0
  124. mmisp_lib-0.1.0/src/mmisp/api_schemas/users/user.py +42 -0
  125. mmisp_lib-0.1.0/src/mmisp/api_schemas/users/users_view_me_response.py +12 -0
  126. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/__init__.py +0 -0
  127. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/check_value_warninglists_body.py +8 -0
  128. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/check_value_warninglists_response.py +14 -0
  129. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/create_warninglist_body.py +220 -0
  130. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/delete_warninglist_response.py +13 -0
  131. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/get_selected_all_warninglists_response.py +14 -0
  132. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/get_selected_warninglists_body.py +9 -0
  133. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/toggle_enable_warninglists_body.py +10 -0
  134. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/toggle_enable_warninglists_response.py +10 -0
  135. mmisp_lib-0.1.0/src/mmisp/api_schemas/warninglists/warninglist_response.py +42 -0
  136. mmisp_lib-0.1.0/src/mmisp/db/__init__.py +0 -0
  137. mmisp_lib-0.1.0/src/mmisp/db/config.py +17 -0
  138. mmisp_lib-0.1.0/src/mmisp/db/database.py +42 -0
  139. mmisp_lib-0.1.0/src/mmisp/db/models/__init__.py +0 -0
  140. mmisp_lib-0.1.0/src/mmisp/db/models/attribute.py +92 -0
  141. mmisp_lib-0.1.0/src/mmisp/db/models/auth_key.py +24 -0
  142. mmisp_lib-0.1.0/src/mmisp/db/models/event.py +62 -0
  143. mmisp_lib-0.1.0/src/mmisp/db/models/feed.py +32 -0
  144. mmisp_lib-0.1.0/src/mmisp/db/models/galaxy.py +22 -0
  145. mmisp_lib-0.1.0/src/mmisp/db/models/galaxy_cluster.py +52 -0
  146. mmisp_lib-0.1.0/src/mmisp/db/models/identity_provider.py +22 -0
  147. mmisp_lib-0.1.0/src/mmisp/db/models/noticelist.py +22 -0
  148. mmisp_lib-0.1.0/src/mmisp/db/models/object.py +39 -0
  149. mmisp_lib-0.1.0/src/mmisp/db/models/organisation.py +26 -0
  150. mmisp_lib-0.1.0/src/mmisp/db/models/role.py +42 -0
  151. mmisp_lib-0.1.0/src/mmisp/db/models/server.py +33 -0
  152. mmisp_lib-0.1.0/src/mmisp/db/models/sharing_group.py +43 -0
  153. mmisp_lib-0.1.0/src/mmisp/db/models/sighting.py +21 -0
  154. mmisp_lib-0.1.0/src/mmisp/db/models/tag.py +19 -0
  155. mmisp_lib-0.1.0/src/mmisp/db/models/taxonomy.py +41 -0
  156. mmisp_lib-0.1.0/src/mmisp/db/models/user.py +44 -0
  157. mmisp_lib-0.1.0/src/mmisp/db/models/user_setting.py +29 -0
  158. mmisp_lib-0.1.0/src/mmisp/db/models/warninglist.py +33 -0
  159. mmisp_lib-0.1.0/src/mmisp/db/print_changes.py +59 -0
  160. mmisp_lib-0.1.0/src/mmisp/lib/__init__.py +0 -0
  161. mmisp_lib-0.1.0/src/mmisp/lib/attributes.py +1386 -0
  162. mmisp_lib-0.1.0/src/mmisp_lib.egg-info/PKG-INFO +77 -0
  163. mmisp_lib-0.1.0/src/mmisp_lib.egg-info/SOURCES.txt +164 -0
  164. mmisp_lib-0.1.0/src/mmisp_lib.egg-info/dependency_links.txt +1 -0
  165. mmisp_lib-0.1.0/src/mmisp_lib.egg-info/requires.txt +25 -0
  166. mmisp_lib-0.1.0/src/mmisp_lib.egg-info/top_level.txt +1 -0
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.1
2
+ Name: mmisp-lib
3
+ Version: 0.1.0
4
+ Requires-Python: >=3.11.0
5
+ Description-Content-Type: text/markdown
6
+ Requires-Dist: fastapi==0.104.1
7
+ Requires-Dist: SQLAlchemy[asyncio]==1.4.46
8
+ Requires-Dist: pydantic==1.10.13
9
+ Requires-Dist: uvicorn==0.24.0.post1
10
+ Requires-Dist: python-dotenv==1.0.0
11
+ Requires-Dist: alembic==1.8.1
12
+ Requires-Dist: aiomysql==0.2.0
13
+ Requires-Dist: aiosqlite==0.20.0
14
+ Requires-Dist: PyJWT==2.8.0
15
+ Requires-Dist: httpx==0.26.0
16
+ Requires-Dist: passlib==1.7.4
17
+ Requires-Dist: argon2-cffi==23.1.0
18
+ Requires-Dist: bcrypt==4.1.2
19
+ Requires-Dist: nanoid==2.0.0
20
+ Requires-Dist: cryptography==42.0.5
21
+ Provides-Extra: dev
22
+ Requires-Dist: ruff==0.3.7; extra == "dev"
23
+ Requires-Dist: mypy==1.8.0; extra == "dev"
24
+ Requires-Dist: pre-commit==3.6.0; extra == "dev"
25
+ Requires-Dist: pytest==8.0.0; extra == "dev"
26
+ Requires-Dist: pytest-asyncio==0.23.5.post1; extra == "dev"
27
+ Requires-Dist: pytest-cov==4.1.0; extra == "dev"
28
+ Requires-Dist: respx==0.20.2; extra == "dev"
29
+ Requires-Dist: mysql-connector-python==8.3.0; extra == "dev"
30
+
31
+ # Modern MISP - API
32
+
33
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Conventional Commits](https://img.shields.io/badge/Conventional_Commits-1.0.0-orange.svg)](https://conventionalcommits.org)
34
+
35
+ ## Requirements
36
+
37
+ - [Docker](https://www.docker.com) `latest-stable`
38
+
39
+ ## Getting Started
40
+
41
+ Clone the project and install Python version `3.11.0`. It is recommended to install Python using [pyenv](https://github.com/pyenv/pyenv#installation). Then install all dependencies by typing `make setup` into your terminal and start your local database container using `make up`.
42
+
43
+ Create a file called `.env` and copy the contents of `.env.example` into it. Finally, start the development server using `make dev`.
44
+
45
+ You should now be able to access the api on `localhost:4000`.
46
+
47
+ Run tests using `make test` (local database container required running) or `make test/lite`.
48
+
49
+ ## Setting up your IDE
50
+
51
+ Be sure to use the newly created virtual env as your interpreter (`./venv/bin/python`). Also install the [Ruff](https://docs.astral.sh/ruff/integrations/) extension for your IDE and set `Ruff` as your default code formatter. It is recommended to activate formatting your code on every save.
52
+
53
+ ## Best Practices
54
+
55
+ ### General Guidelines
56
+
57
+ The following are some guidelines for writing code, in no particular order:
58
+
59
+ - Try to write clean code
60
+ - Use the "early return" pattern, do you really need that `else` block?
61
+ - Add correct types wherever possible, reduce `Any` occurrences as much as possible
62
+ - Reduce database calls
63
+ - Be consistent within your code, and within the rest of the codebase
64
+ - Use whitespace generously, to group and separate lines of code
65
+ - Be explicit, magic is great until it is not
66
+
67
+ ### Endpoint Ordering
68
+
69
+ Try to order endpoints using CRUD so that the following order is achieved:
70
+
71
+ - Create a {resource}
72
+ - Read / Get a {resource}
73
+ - Update a {resource}
74
+ - Delete a {resource}
75
+ - Get all {resource}s
76
+ - More niche endpoints
77
+ - Deprecated endpoints
@@ -0,0 +1,47 @@
1
+ # Modern MISP - API
2
+
3
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Conventional Commits](https://img.shields.io/badge/Conventional_Commits-1.0.0-orange.svg)](https://conventionalcommits.org)
4
+
5
+ ## Requirements
6
+
7
+ - [Docker](https://www.docker.com) `latest-stable`
8
+
9
+ ## Getting Started
10
+
11
+ Clone the project and install Python version `3.11.0`. It is recommended to install Python using [pyenv](https://github.com/pyenv/pyenv#installation). Then install all dependencies by typing `make setup` into your terminal and start your local database container using `make up`.
12
+
13
+ Create a file called `.env` and copy the contents of `.env.example` into it. Finally, start the development server using `make dev`.
14
+
15
+ You should now be able to access the api on `localhost:4000`.
16
+
17
+ Run tests using `make test` (local database container required running) or `make test/lite`.
18
+
19
+ ## Setting up your IDE
20
+
21
+ Be sure to use the newly created virtual env as your interpreter (`./venv/bin/python`). Also install the [Ruff](https://docs.astral.sh/ruff/integrations/) extension for your IDE and set `Ruff` as your default code formatter. It is recommended to activate formatting your code on every save.
22
+
23
+ ## Best Practices
24
+
25
+ ### General Guidelines
26
+
27
+ The following are some guidelines for writing code, in no particular order:
28
+
29
+ - Try to write clean code
30
+ - Use the "early return" pattern, do you really need that `else` block?
31
+ - Add correct types wherever possible, reduce `Any` occurrences as much as possible
32
+ - Reduce database calls
33
+ - Be consistent within your code, and within the rest of the codebase
34
+ - Use whitespace generously, to group and separate lines of code
35
+ - Be explicit, magic is great until it is not
36
+
37
+ ### Endpoint Ordering
38
+
39
+ Try to order endpoints using CRUD so that the following order is achieved:
40
+
41
+ - Create a {resource}
42
+ - Read / Get a {resource}
43
+ - Update a {resource}
44
+ - Delete a {resource}
45
+ - Get all {resource}s
46
+ - More niche endpoints
47
+ - Deprecated endpoints
@@ -0,0 +1,50 @@
1
+ [project]
2
+ name = "mmisp-lib"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = []
6
+ readme = "README.md"
7
+ requires-python = ">=3.11.0"
8
+
9
+
10
+ dependencies = [
11
+ "fastapi==0.104.1",
12
+ "SQLAlchemy[asyncio]==1.4.46",
13
+ "pydantic==1.10.13",
14
+ "uvicorn==0.24.0.post1",
15
+ "python-dotenv==1.0.0",
16
+ "alembic==1.8.1",
17
+ "aiomysql==0.2.0",
18
+ "aiosqlite==0.20.0",
19
+ "PyJWT==2.8.0",
20
+ "httpx==0.26.0",
21
+ "passlib==1.7.4",
22
+ "argon2-cffi==23.1.0",
23
+ "bcrypt==4.1.2",
24
+ "nanoid==2.0.0",
25
+ "cryptography==42.0.5",
26
+ ]
27
+
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "ruff==0.3.7",
32
+ "mypy==1.8.0",
33
+ "pre-commit==3.6.0",
34
+ "pytest==8.0.0",
35
+ "pytest-asyncio==0.23.5.post1",
36
+ "pytest-cov==4.1.0",
37
+ "respx==0.20.2",
38
+ "mysql-connector-python==8.3.0",
39
+ ]
40
+
41
+ [tool.ruff]
42
+ fix = true
43
+ line-length = 120
44
+ required-version = "0.3.7"
45
+ select = ["E", "F", "W", "I", "ICN", "ANN"]
46
+ ignore = ["ANN002", "ANN003", "ANN401"]
47
+ src = ["src"]
48
+
49
+ [tool.coverage.run]
50
+ concurrency = ["greenlet", "thread"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,34 @@
1
+ from typing import Any, Optional
2
+
3
+ from pydantic import BaseModel, root_validator
4
+
5
+
6
+ class AddAttributeBody(BaseModel):
7
+ type: str
8
+ value: Optional[str]
9
+ value1: Optional[str]
10
+ value2: str | None = None
11
+ event_id: str | None = None
12
+ object_id: str | None = None
13
+ object_relation: str | None = None
14
+ category: str | None = None
15
+ to_ids: bool | None = None
16
+ uuid: str | None = None
17
+ timestamp: str | None = None
18
+ distribution: str | None = None
19
+ sharing_group_id: str | None = None
20
+ comment: str | None = None
21
+ deleted: bool | None = None
22
+ disable_correlation: bool | None = None
23
+ first_seen: str | None = None
24
+ last_seen: str | None = None
25
+
26
+ @root_validator
27
+ def ensure_value_or_value1_is_set(cls, data: dict[str, Any]) -> Optional[dict[str, Any]]: # noqa: ANN101
28
+ required_values: list[str] = [str(data.get("value")), str(data.get("value1"))]
29
+ if all(item is None for item in required_values):
30
+ raise ValueError("value or value1 has to be set")
31
+ return data
32
+
33
+ class Config:
34
+ orm_mode = True
@@ -0,0 +1,33 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class AddAttributeAttributes(BaseModel):
7
+ id: str
8
+ event_id: str
9
+ object_id: str
10
+ object_relation: Optional[str] = Field(..., nullable=True)
11
+ category: str
12
+ type: str
13
+ value: str
14
+ value1: str
15
+ value2: str
16
+ to_ids: bool
17
+ uuid: str
18
+ timestamp: str
19
+ distribution: str
20
+ sharing_group_id: str
21
+ comment: str
22
+ deleted: bool
23
+ disable_correlation: bool
24
+ first_seen: Optional[str] = Field(..., nullable=True)
25
+ last_seen: Optional[str] = Field(..., nullable=True)
26
+ attribute_tag: list[str] = Field([], alias="AttributeTag")
27
+
28
+
29
+ class AddAttributeResponse(BaseModel):
30
+ Attribute: AddAttributeAttributes
31
+
32
+ class Config:
33
+ orm_mode = True
@@ -0,0 +1,13 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class AddRemoveTagAttributeResponse(BaseModel):
7
+ saved: bool
8
+ success: Optional[str]
9
+ check_publish: Optional[bool]
10
+ errors: Optional[str]
11
+
12
+ class Config:
13
+ orm_mode = True
@@ -0,0 +1,8 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class DeleteAttributeResponse(BaseModel):
5
+ message: str
6
+
7
+ class Config:
8
+ orm_mode = True
@@ -0,0 +1,9 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class DeleteSelectedAttributeBody(BaseModel):
5
+ id: str # id = "all" deletes all attributes in the event
6
+ allow_hard_delete: bool | None = None
7
+
8
+ class Config:
9
+ orm_mode = True
@@ -0,0 +1,13 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class DeleteSelectedAttributeResponse(BaseModel):
5
+ saved: bool
6
+ success: bool
7
+ name: str
8
+ message: str
9
+ url: str
10
+ id: str
11
+
12
+ class Config:
13
+ orm_mode = True
@@ -0,0 +1,24 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class EditAttributeBody(BaseModel):
5
+ type: str | None = None
6
+ value: str | None = None
7
+ value1: str | None = None
8
+ value2: str | None = None
9
+ object_id: str | None = None
10
+ object_relation: str | None = None
11
+ category: str | None = None
12
+ to_ids: bool | None = None
13
+ uuid: str | None = None
14
+ timestamp: str | None = None
15
+ distribution: str | None = None
16
+ sharing_group_id: str | None = None
17
+ comment: str | None = None
18
+ deleted: bool | None = None
19
+ disable_correlation: bool | None = None
20
+ first_seen: str | None = None
21
+ last_seen: str | None = None
22
+
23
+ class Config:
24
+ orm_mode = True
@@ -0,0 +1,42 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class EditAttributeTag(BaseModel):
5
+ id: str
6
+ name: str
7
+ colour: str
8
+ exportable: str
9
+ user_id: str
10
+ hide_tag: bool
11
+ numerical_value: int
12
+ is_galaxy: bool
13
+ is_costum_galaxy: bool
14
+ local_only: bool
15
+
16
+
17
+ class EditAttributeAttributes(BaseModel):
18
+ id: str
19
+ event_id: str
20
+ object_id: str
21
+ object_relation: str | None = None
22
+ category: str
23
+ type: str
24
+ value: str
25
+ to_ids: bool
26
+ uuid: str
27
+ timestamp: str
28
+ distribution: str
29
+ sharing_group_id: str
30
+ comment: str | None = None
31
+ deleted: bool
32
+ disable_correlation: bool
33
+ first_seen: str | None = None
34
+ last_seen: str | None = None
35
+ tag: list[EditAttributeTag]
36
+
37
+
38
+ class EditAttributeResponse(BaseModel):
39
+ Attribute: EditAttributeAttributes
40
+
41
+ class Config:
42
+ orm_mode = True
@@ -0,0 +1,38 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ from pydantic import BaseModel, validator
4
+
5
+
6
+ class GetAllAttributesResponse(BaseModel):
7
+ id: str
8
+ event_id: str | None = None
9
+ object_id: str | None = None
10
+ object_relation: str | None = None
11
+ category: str | None = None
12
+ type: str
13
+ value1: str | None = None
14
+ value2: str | None = None
15
+ to_ids: bool | None = None
16
+ uuid: str | None = None
17
+ timestamp: str | None = None
18
+ distribution: str | None = None
19
+ sharing_group_id: str | None = None
20
+ comment: str | None = None
21
+ deleted: bool | None = None
22
+ disable_correlation: bool | None = None
23
+ first_seen: str | None = None
24
+ last_seen: str | None = None
25
+ value: str | None = None
26
+
27
+ @validator("sharing_group_id", always=True)
28
+ def check_sharing_group_id(cls, value: Any, values: Dict[str, Any]) -> Optional[int]: # noqa: ANN101
29
+ """
30
+ If distribution equals 4, sharing_group_id will be shown.
31
+ """
32
+ distribution = values.get("distribution", None)
33
+ if distribution == "4" and value is not None:
34
+ return value
35
+ return None
36
+
37
+ class Config:
38
+ orm_mode = True
@@ -0,0 +1,41 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class GetAttributeTag(BaseModel):
7
+ id: str
8
+ name: str
9
+ colour: str
10
+ numerical_value: int | None = None
11
+ is_galaxy: bool
12
+ local: bool
13
+
14
+
15
+ class GetAttributeAttributes(BaseModel):
16
+ id: str
17
+ event_id: str
18
+ object_id: str
19
+ object_relation: Optional[str] = Field(..., nullable=True)
20
+ category: str
21
+ type: str
22
+ value: str
23
+ to_ids: bool
24
+ uuid: str
25
+ timestamp: str
26
+ distribution: str
27
+ sharing_group_id: str
28
+ comment: str | None = None
29
+ deleted: bool
30
+ disable_correlation: bool
31
+ first_seen: Optional[str] = Field(..., nullable=True)
32
+ last_seen: Optional[str] = Field(..., nullable=True)
33
+ event_uuid: str
34
+ tag: list[GetAttributeTag] | None = None
35
+
36
+
37
+ class GetAttributeResponse(BaseModel):
38
+ Attribute: GetAttributeAttributes
39
+
40
+ class Config:
41
+ orm_mode = True
@@ -0,0 +1,137 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class GetAttributeStatisticsTypesResponse(BaseModel):
5
+ as_: str = Field(alias="AS")
6
+ attachment: str
7
+ authentihash: str
8
+ boolean: str
9
+ btc: str
10
+ campaign_id: str = Field(alias="campaign-id")
11
+ campaign_name: str = Field(alias="campaign-name")
12
+ comment: str
13
+ cookie: str
14
+ counter: str
15
+ cpe: str
16
+ date_of_birth: str = Field(alias="date-of-birth")
17
+ datetime: str
18
+ dns_soa_email: str = Field(alias="dns-soa-email")
19
+ domain: str
20
+ domain_ip: str = Field(alias="domain|ip")
21
+ email: str
22
+ email_attachment: str = Field(alias="email-attachment")
23
+ email_body: str = Field(alias="email-body")
24
+ email_dst: str = Field(alias="email-dst")
25
+ email_message_id: str = Field(alias="email-message-id")
26
+ email_mime_boundary: str = Field(alias="email-mime-boundary")
27
+ email_reply_to: str = Field(alias="email-reply-to")
28
+ email_src: str = Field(alias="email-src")
29
+ email_src_display_name: str = Field(alias="email-src-display-name")
30
+ email_subject: str = Field(alias="email-subject")
31
+ email_x_mailer: str = Field(alias="email-x-mailer")
32
+ filename: str
33
+ filename_pattern: str = Field(alias="filename-pattern")
34
+ filename_md5: str = Field(alias="filename|md5")
35
+ filename_sha1: str = Field(alias="filename|sha1")
36
+ filename_sha256: str = Field(alias="filename|sha256")
37
+ first_name: str = Field(alias="first-name")
38
+ float: str
39
+ full_name: str = Field(alias="full-name")
40
+ gender: str
41
+ github_repository: str = Field(alias="github-repository")
42
+ github_username: str = Field(alias="github-username")
43
+ hex: str
44
+ hostname: str
45
+ http_method: str = Field(alias="http-method")
46
+ imphash: str
47
+ ip_dst: str = Field(alias="ip-dst")
48
+ ip_dst_port: str = Field(alias="ip-dst|port")
49
+ ip_src: str = Field(alias="ip-src")
50
+ ip_src_port: str = Field(alias="ip-src|port")
51
+ ja3_fingerprint_md5: str = Field(alias="ja3-fingerprint-md5")
52
+ jabber_id: str = Field(alias="jabber-id")
53
+ jarm_fingerprint: str = Field(alias="jarm-fingerprint")
54
+ last_name: str = Field(alias="last-name")
55
+ link: str
56
+ malware_sample: str = Field(alias="malware-sample")
57
+ md5: str
58
+ mime_type: str = Field(alias="mime-type")
59
+ mobile_application_id: str = Field(alias="mobile-application-id")
60
+ mutex: str
61
+ named_pipe: str = Field(alias="named pipe")
62
+ nationality: str
63
+ other: str
64
+ passport_country: str = Field(alias="passport-country")
65
+ passport_expiration: str = Field(alias="passport-expiration")
66
+ passport_number: str = Field(alias="passport-number")
67
+ pattern_in_file: str = Field(alias="pattern-in-file")
68
+ pattern_in_memory: str = Field(alias="pattern-in-memory")
69
+ pattern_in_traffic: str = Field(alias="pattern-in-traffic")
70
+ pdb: str
71
+ pehash: str
72
+ phone_number: str = Field(alias="phone-number")
73
+ place_of_birth: str = Field(alias="place-of-birth")
74
+ port: str
75
+ regkey: str
76
+ regkey_value: str = Field(alias="regkey|value")
77
+ sha1: str
78
+ sha224: str
79
+ sha256: str
80
+ sha384: str
81
+ sha512: str
82
+ sigma: str
83
+ size_in_bytes: str = Field(alias="size-in-bytes")
84
+ snort: str
85
+ ssdeep: str
86
+ stix2_pattern: str = Field(alias="stix2-pattern")
87
+ target_external: str = Field(alias="target-external")
88
+ target_location: str = Field(alias="target-location")
89
+ target_machine: str = Field(alias="target-machine")
90
+ target_org: str = Field(alias="target-org")
91
+ target_user: str = Field(alias="target-user")
92
+ text: str
93
+ threat_actor: str = Field(alias="threat-actor")
94
+ tlsh: str
95
+ uri: str
96
+ url: str
97
+ user_agent: str = Field(alias="user-agent")
98
+ vhash: str
99
+ vulnerability: str
100
+ weakness: str
101
+ whois_creation_date: str = Field(alias="whois-creation-date")
102
+ whois_registrant_email: str = Field(alias="whois-registrant-email")
103
+ whois_registrant_name: str = Field(alias="whois-registrant-name")
104
+ whois_registrant_org: str = Field(alias="whois-registrant-org")
105
+ whois_registrant_phone: str = Field(alias="whois-registrant-phone")
106
+ whois_registrar: str = Field(alias="whois-registrar")
107
+ windows_scheduled_task: str = Field(alias="windows-scheduled-task")
108
+ windows_service_name: str = Field(alias="windows-service-name")
109
+ x509_fingerprint_md5: str = Field(alias="x509-fingerprint-md5")
110
+ x509_fingerprint_sha1: str = Field(alias="x509-fingerprint-sha1")
111
+ x509_fingerprint_sha256: str = Field(alias="x509-fingerprint-sha256")
112
+ yara: str
113
+
114
+ class Config:
115
+ orm_mode = True
116
+
117
+
118
+ class GetAttributeStatisticsCategoriesResponse(BaseModel):
119
+ antivirus_detection: str = Field(alias="Antivirus detection")
120
+ artifacts_dropped: str = Field(alias="Artifacts dropped")
121
+ attribution: str = Field(alias="Attribution")
122
+ external_analysis: str = Field(alias="External analysis")
123
+ financial_fraud: str = Field(alias="Financial fraud")
124
+ internal_reference: str = Field(alias="Internal reference")
125
+ network_activity: str = Field(alias="Network activity")
126
+ other: str = Field(alias="Other")
127
+ payload_delivery: str = Field(alias="Payload delivery")
128
+ payload_installation: str = Field(alias="Payload installation")
129
+ payload_type: str = Field(alias="Payload type")
130
+ persistence_mechanism: str = Field(alias="Persistence mechanism")
131
+ person: str = Field(alias="Person")
132
+ social_network: str = Field(alias="Social network")
133
+ support__tool: str = Field(alias="Support Tool")
134
+ targeting_data: str = Field(alias="Targeting data")
135
+
136
+ class Config:
137
+ orm_mode = True
@@ -0,0 +1,29 @@
1
+ from pydantic import BaseModel
2
+
3
+ from mmisp.lib.attributes import AttributeCategories, default_category, inverted_categories, to_ids
4
+
5
+
6
+ class GetDescribeTypesAttributes(BaseModel):
7
+ sane_defaults: dict = {}
8
+ for k, v in to_ids.items():
9
+ sane_defaults.update(
10
+ {
11
+ k: {
12
+ "default_category": default_category[k],
13
+ "to_ids": v,
14
+ }
15
+ }
16
+ )
17
+
18
+ types: list[str] = list(default_category.keys())
19
+
20
+ categories: list[str] = [member.value for member in AttributeCategories]
21
+
22
+ category_type_mappings: dict = inverted_categories
23
+
24
+
25
+ class GetDescribeTypesResponse(BaseModel):
26
+ result: GetDescribeTypesAttributes
27
+
28
+ class Config:
29
+ orm_mode = True
@@ -0,0 +1,25 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class RestoreAttributeResponse(BaseModel):
5
+ id: str
6
+ event_id: str
7
+ object_id: str
8
+ object_relation: str
9
+ category: str
10
+ type: str
11
+ value: str
12
+ to_ids: bool
13
+ uuid: str
14
+ timestamp: str
15
+ distribution: str
16
+ sharing_group_id: str
17
+ comment: str
18
+ deleted: bool
19
+ disable_correlation: bool
20
+ first_seen: str
21
+ last_seen: str
22
+ event_uuid: str # new
23
+
24
+ class Config:
25
+ orm_mode = True