amsdal 0.4.13__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

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 (269) hide show
  1. amsdal/Third-Party Materials - AMSDAL Dependencies - License Notices.md +1334 -0
  2. amsdal/__about__.py +4 -0
  3. amsdal/__about__.pyi +1 -0
  4. amsdal/__init__.py +23 -0
  5. amsdal/__init__.pyi +9 -0
  6. amsdal/__migrations__/0000_initial.py +217 -0
  7. amsdal/__migrations__/0001_datetime_type.py +18 -0
  8. amsdal/__migrations__/0002_fixture_order.py +44 -0
  9. amsdal/__migrations__/0003_schema_type_in_class_meta.py +44 -0
  10. amsdal/cloud/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  11. amsdal/cloud/__init__.pyi +0 -0
  12. amsdal/cloud/client.cpython-311-x86_64-linux-gnu.so +0 -0
  13. amsdal/cloud/client.pyi +57 -0
  14. amsdal/cloud/constants.cpython-311-x86_64-linux-gnu.so +0 -0
  15. amsdal/cloud/constants.pyi +13 -0
  16. amsdal/cloud/enums.cpython-311-x86_64-linux-gnu.so +0 -0
  17. amsdal/cloud/enums.pyi +68 -0
  18. amsdal/cloud/models/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  19. amsdal/cloud/models/__init__.pyi +0 -0
  20. amsdal/cloud/models/base.cpython-311-x86_64-linux-gnu.so +0 -0
  21. amsdal/cloud/models/base.pyi +247 -0
  22. amsdal/cloud/services/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  23. amsdal/cloud/services/__init__.pyi +0 -0
  24. amsdal/cloud/services/actions/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  25. amsdal/cloud/services/actions/__init__.pyi +0 -0
  26. amsdal/cloud/services/actions/add_allowlist_ip.cpython-311-x86_64-linux-gnu.so +0 -0
  27. amsdal/cloud/services/actions/add_allowlist_ip.pyi +19 -0
  28. amsdal/cloud/services/actions/add_basic_auth.cpython-311-x86_64-linux-gnu.so +0 -0
  29. amsdal/cloud/services/actions/add_basic_auth.pyi +21 -0
  30. amsdal/cloud/services/actions/add_dependency.cpython-311-x86_64-linux-gnu.so +0 -0
  31. amsdal/cloud/services/actions/add_dependency.pyi +19 -0
  32. amsdal/cloud/services/actions/add_secret.cpython-311-x86_64-linux-gnu.so +0 -0
  33. amsdal/cloud/services/actions/add_secret.pyi +20 -0
  34. amsdal/cloud/services/actions/base.cpython-311-x86_64-linux-gnu.so +0 -0
  35. amsdal/cloud/services/actions/base.pyi +122 -0
  36. amsdal/cloud/services/actions/create_deploy.cpython-311-x86_64-linux-gnu.so +0 -0
  37. amsdal/cloud/services/actions/create_deploy.pyi +41 -0
  38. amsdal/cloud/services/actions/create_env.cpython-311-x86_64-linux-gnu.so +0 -0
  39. amsdal/cloud/services/actions/create_env.pyi +19 -0
  40. amsdal/cloud/services/actions/create_session.cpython-311-x86_64-linux-gnu.so +0 -0
  41. amsdal/cloud/services/actions/create_session.pyi +17 -0
  42. amsdal/cloud/services/actions/delete_allowlist_ip.cpython-311-x86_64-linux-gnu.so +0 -0
  43. amsdal/cloud/services/actions/delete_allowlist_ip.pyi +19 -0
  44. amsdal/cloud/services/actions/delete_basic_auth.cpython-311-x86_64-linux-gnu.so +0 -0
  45. amsdal/cloud/services/actions/delete_basic_auth.pyi +20 -0
  46. amsdal/cloud/services/actions/delete_dependency.cpython-311-x86_64-linux-gnu.so +0 -0
  47. amsdal/cloud/services/actions/delete_dependency.pyi +21 -0
  48. amsdal/cloud/services/actions/delete_env.cpython-311-x86_64-linux-gnu.so +0 -0
  49. amsdal/cloud/services/actions/delete_env.pyi +21 -0
  50. amsdal/cloud/services/actions/delete_secret.cpython-311-x86_64-linux-gnu.so +0 -0
  51. amsdal/cloud/services/actions/delete_secret.pyi +21 -0
  52. amsdal/cloud/services/actions/destroy_deploy.cpython-311-x86_64-linux-gnu.so +0 -0
  53. amsdal/cloud/services/actions/destroy_deploy.pyi +18 -0
  54. amsdal/cloud/services/actions/expose_db.cpython-311-x86_64-linux-gnu.so +0 -0
  55. amsdal/cloud/services/actions/expose_db.pyi +22 -0
  56. amsdal/cloud/services/actions/get_basic_auth_credentials.cpython-311-x86_64-linux-gnu.so +0 -0
  57. amsdal/cloud/services/actions/get_basic_auth_credentials.pyi +21 -0
  58. amsdal/cloud/services/actions/get_monitoring_info.cpython-311-x86_64-linux-gnu.so +0 -0
  59. amsdal/cloud/services/actions/get_monitoring_info.pyi +21 -0
  60. amsdal/cloud/services/actions/list_dependencies.cpython-311-x86_64-linux-gnu.so +0 -0
  61. amsdal/cloud/services/actions/list_dependencies.pyi +21 -0
  62. amsdal/cloud/services/actions/list_deploys.cpython-311-x86_64-linux-gnu.so +0 -0
  63. amsdal/cloud/services/actions/list_deploys.pyi +19 -0
  64. amsdal/cloud/services/actions/list_envs.cpython-311-x86_64-linux-gnu.so +0 -0
  65. amsdal/cloud/services/actions/list_envs.pyi +20 -0
  66. amsdal/cloud/services/actions/list_secrets.cpython-311-x86_64-linux-gnu.so +0 -0
  67. amsdal/cloud/services/actions/list_secrets.pyi +22 -0
  68. amsdal/cloud/services/actions/manager.cpython-311-x86_64-linux-gnu.so +0 -0
  69. amsdal/cloud/services/actions/manager.pyi +278 -0
  70. amsdal/cloud/services/actions/signup_action.cpython-311-x86_64-linux-gnu.so +0 -0
  71. amsdal/cloud/services/actions/signup_action.pyi +20 -0
  72. amsdal/cloud/services/actions/update_deploy.cpython-311-x86_64-linux-gnu.so +0 -0
  73. amsdal/cloud/services/actions/update_deploy.pyi +19 -0
  74. amsdal/cloud/services/auth/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  75. amsdal/cloud/services/auth/__init__.pyi +0 -0
  76. amsdal/cloud/services/auth/base.cpython-311-x86_64-linux-gnu.so +0 -0
  77. amsdal/cloud/services/auth/base.pyi +6 -0
  78. amsdal/cloud/services/auth/credentials.cpython-311-x86_64-linux-gnu.so +0 -0
  79. amsdal/cloud/services/auth/credentials.pyi +30 -0
  80. amsdal/cloud/services/auth/manager.cpython-311-x86_64-linux-gnu.so +0 -0
  81. amsdal/cloud/services/auth/manager.pyi +26 -0
  82. amsdal/cloud/services/auth/signup_service.cpython-311-x86_64-linux-gnu.so +0 -0
  83. amsdal/cloud/services/auth/signup_service.pyi +32 -0
  84. amsdal/cloud/services/auth/token.cpython-311-x86_64-linux-gnu.so +0 -0
  85. amsdal/cloud/services/auth/token.pyi +27 -0
  86. amsdal/configs/__init__.py +0 -0
  87. amsdal/configs/__init__.pyi +0 -0
  88. amsdal/configs/constants.py +33 -0
  89. amsdal/configs/constants.pyi +22 -0
  90. amsdal/configs/main.py +258 -0
  91. amsdal/configs/main.pyi +173 -0
  92. amsdal/context/__init__.py +0 -0
  93. amsdal/context/__init__.pyi +0 -0
  94. amsdal/context/manager.py +69 -0
  95. amsdal/context/manager.pyi +50 -0
  96. amsdal/contrib/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  97. amsdal/contrib/__init__.pyi +0 -0
  98. amsdal/contrib/app_config.py +7 -0
  99. amsdal/contrib/app_config.pyi +6 -0
  100. amsdal/contrib/auth/__init__.py +0 -0
  101. amsdal/contrib/auth/__init__.pyi +0 -0
  102. amsdal/contrib/auth/app.py +27 -0
  103. amsdal/contrib/auth/app.pyi +15 -0
  104. amsdal/contrib/auth/decorators/__init__.py +35 -0
  105. amsdal/contrib/auth/decorators/__init__.pyi +6 -0
  106. amsdal/contrib/auth/errors.py +7 -0
  107. amsdal/contrib/auth/errors.pyi +4 -0
  108. amsdal/contrib/auth/fixtures/basic_permissions.json +64 -0
  109. amsdal/contrib/auth/lifecycle/__init__.py +0 -0
  110. amsdal/contrib/auth/lifecycle/__init__.pyi +0 -0
  111. amsdal/contrib/auth/lifecycle/consumer.py +394 -0
  112. amsdal/contrib/auth/lifecycle/consumer.pyi +108 -0
  113. amsdal/contrib/auth/migrations/0000_initial.py +84 -0
  114. amsdal/contrib/auth/models/__init__.py +0 -0
  115. amsdal/contrib/auth/models/__init__.pyi +0 -0
  116. amsdal/contrib/auth/models/login_session.py +118 -0
  117. amsdal/contrib/auth/models/login_session.pyi +37 -0
  118. amsdal/contrib/auth/models/permission.py +23 -0
  119. amsdal/contrib/auth/models/permission.pyi +18 -0
  120. amsdal/contrib/auth/models/user.py +106 -0
  121. amsdal/contrib/auth/models/user.pyi +46 -0
  122. amsdal/contrib/auth/settings.py +36 -0
  123. amsdal/contrib/auth/settings.pyi +26 -0
  124. amsdal/contrib/frontend_configs/__init__.py +0 -0
  125. amsdal/contrib/frontend_configs/__init__.pyi +0 -0
  126. amsdal/contrib/frontend_configs/app.py +24 -0
  127. amsdal/contrib/frontend_configs/app.pyi +19 -0
  128. amsdal/contrib/frontend_configs/constants.py +1 -0
  129. amsdal/contrib/frontend_configs/constants.pyi +1 -0
  130. amsdal/contrib/frontend_configs/conversion/__init__.py +5 -0
  131. amsdal/contrib/frontend_configs/conversion/__init__.pyi +3 -0
  132. amsdal/contrib/frontend_configs/conversion/convert.py +286 -0
  133. amsdal/contrib/frontend_configs/conversion/convert.pyi +22 -0
  134. amsdal/contrib/frontend_configs/lifecycle/__init__.py +0 -0
  135. amsdal/contrib/frontend_configs/lifecycle/__init__.pyi +0 -0
  136. amsdal/contrib/frontend_configs/lifecycle/consumer.py +306 -0
  137. amsdal/contrib/frontend_configs/lifecycle/consumer.pyi +98 -0
  138. amsdal/contrib/frontend_configs/migrations/0000_initial.py +256 -0
  139. amsdal/contrib/frontend_configs/models/__init__.py +0 -0
  140. amsdal/contrib/frontend_configs/models/__init__.pyi +0 -0
  141. amsdal/contrib/frontend_configs/models/frontend_activator_config.py +22 -0
  142. amsdal/contrib/frontend_configs/models/frontend_activator_config.pyi +12 -0
  143. amsdal/contrib/frontend_configs/models/frontend_config_async_validator.py +11 -0
  144. amsdal/contrib/frontend_configs/models/frontend_config_async_validator.pyi +7 -0
  145. amsdal/contrib/frontend_configs/models/frontend_config_control_action.py +54 -0
  146. amsdal/contrib/frontend_configs/models/frontend_config_control_action.pyi +32 -0
  147. amsdal/contrib/frontend_configs/models/frontend_config_group_validator.py +21 -0
  148. amsdal/contrib/frontend_configs/models/frontend_config_group_validator.pyi +11 -0
  149. amsdal/contrib/frontend_configs/models/frontend_config_option.py +12 -0
  150. amsdal/contrib/frontend_configs/models/frontend_config_option.pyi +8 -0
  151. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base.py +17 -0
  152. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base.pyi +8 -0
  153. amsdal/contrib/frontend_configs/models/frontend_config_slider_option.py +13 -0
  154. amsdal/contrib/frontend_configs/models/frontend_config_slider_option.pyi +9 -0
  155. amsdal/contrib/frontend_configs/models/frontend_config_text_mask.py +14 -0
  156. amsdal/contrib/frontend_configs/models/frontend_config_text_mask.pyi +10 -0
  157. amsdal/contrib/frontend_configs/models/frontend_config_validator.py +28 -0
  158. amsdal/contrib/frontend_configs/models/frontend_config_validator.pyi +15 -0
  159. amsdal/contrib/frontend_configs/models/frontend_control_config.py +87 -0
  160. amsdal/contrib/frontend_configs/models/frontend_control_config.pyi +35 -0
  161. amsdal/contrib/frontend_configs/models/frontend_model_config.py +14 -0
  162. amsdal/contrib/frontend_configs/models/frontend_model_config.pyi +9 -0
  163. amsdal/contrib/frontend_configs/utils.py +29 -0
  164. amsdal/contrib/frontend_configs/utils.pyi +17 -0
  165. amsdal/errors.py +31 -0
  166. amsdal/errors.pyi +12 -0
  167. amsdal/fixtures/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  168. amsdal/fixtures/__init__.pyi +0 -0
  169. amsdal/fixtures/manager.cpython-311-x86_64-linux-gnu.so +0 -0
  170. amsdal/fixtures/manager.pyi +170 -0
  171. amsdal/fixtures/utils.cpython-311-x86_64-linux-gnu.so +0 -0
  172. amsdal/fixtures/utils.pyi +9 -0
  173. amsdal/manager.cpython-311-x86_64-linux-gnu.so +0 -0
  174. amsdal/manager.pyi +265 -0
  175. amsdal/mixins/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  176. amsdal/mixins/__init__.pyi +0 -0
  177. amsdal/mixins/class_versions_mixin.cpython-311-x86_64-linux-gnu.so +0 -0
  178. amsdal/mixins/class_versions_mixin.pyi +12 -0
  179. amsdal/models/__init__.py +19 -0
  180. amsdal/models/__init__.pyi +9 -0
  181. amsdal/models/core/__init__.py +0 -0
  182. amsdal/models/core/__init__.pyi +0 -0
  183. amsdal/models/core/class_object.py +37 -0
  184. amsdal/models/core/class_object.pyi +24 -0
  185. amsdal/models/core/class_object_meta.py +26 -0
  186. amsdal/models/core/class_object_meta.pyi +15 -0
  187. amsdal/models/core/class_property.py +20 -0
  188. amsdal/models/core/class_property.pyi +11 -0
  189. amsdal/models/core/class_property_meta.py +15 -0
  190. amsdal/models/core/class_property_meta.pyi +10 -0
  191. amsdal/models/core/file.py +156 -0
  192. amsdal/models/core/file.pyi +104 -0
  193. amsdal/models/core/fixture.py +25 -0
  194. amsdal/models/core/fixture.pyi +14 -0
  195. amsdal/models/core/option.py +11 -0
  196. amsdal/models/core/option.pyi +8 -0
  197. amsdal/models/core/validator.py +12 -0
  198. amsdal/models/core/validator.pyi +8 -0
  199. amsdal/models/types/__init__.py +0 -0
  200. amsdal/models/types/__init__.pyi +0 -0
  201. amsdal/models/types/object.py +26 -0
  202. amsdal/models/types/object.pyi +16 -0
  203. amsdal/py.typed +0 -0
  204. amsdal/queryset/__init__.py +21 -0
  205. amsdal/queryset/__init__.pyi +6 -0
  206. amsdal/schemas/__init__.py +0 -0
  207. amsdal/schemas/__init__.pyi +0 -0
  208. amsdal/schemas/core/class_object/model.json +31 -0
  209. amsdal/schemas/core/class_object/properties/display_name.py +9 -0
  210. amsdal/schemas/core/class_object_meta/model.json +59 -0
  211. amsdal/schemas/core/class_property/model.json +22 -0
  212. amsdal/schemas/core/class_property_meta/model.json +23 -0
  213. amsdal/schemas/core/file/hooks/pre_create.py +24 -0
  214. amsdal/schemas/core/file/hooks/pre_update.py +24 -0
  215. amsdal/schemas/core/file/model.json +23 -0
  216. amsdal/schemas/core/file/properties/from_file.py +34 -0
  217. amsdal/schemas/core/file/properties/mimetype.py +13 -0
  218. amsdal/schemas/core/file/properties/str.py +6 -0
  219. amsdal/schemas/core/file/properties/to_file.py +24 -0
  220. amsdal/schemas/core/file/properties/validate_data.py +32 -0
  221. amsdal/schemas/core/fixture/model.json +35 -0
  222. amsdal/schemas/core/option/model.json +19 -0
  223. amsdal/schemas/core/validator/model.json +19 -0
  224. amsdal/schemas/interfaces.py +25 -0
  225. amsdal/schemas/interfaces.pyi +20 -0
  226. amsdal/schemas/manager.cpython-311-x86_64-linux-gnu.so +0 -0
  227. amsdal/schemas/manager.py +0 -0
  228. amsdal/schemas/manager.pyi +0 -0
  229. amsdal/schemas/mixins/__init__.py +0 -0
  230. amsdal/schemas/mixins/__init__.pyi +0 -0
  231. amsdal/schemas/mixins/check_dependencies_mixin.py +125 -0
  232. amsdal/schemas/mixins/check_dependencies_mixin.pyi +45 -0
  233. amsdal/schemas/mixins/verify_schemas_mixin.py +96 -0
  234. amsdal/schemas/mixins/verify_schemas_mixin.pyi +33 -0
  235. amsdal/schemas/repository.py +84 -0
  236. amsdal/schemas/repository.pyi +22 -0
  237. amsdal/schemas/types/anything/model.json +7 -0
  238. amsdal/schemas/types/array/model.json +7 -0
  239. amsdal/schemas/types/binary/model.json +7 -0
  240. amsdal/schemas/types/boolean/model.json +17 -0
  241. amsdal/schemas/types/date/model.json +7 -0
  242. amsdal/schemas/types/datetime/model.json +7 -0
  243. amsdal/schemas/types/dictionary/model.json +8 -0
  244. amsdal/schemas/types/number/model.json +8 -0
  245. amsdal/schemas/types/object/model.json +53 -0
  246. amsdal/schemas/types/string/model.json +8 -0
  247. amsdal/schemas/utils.py +16 -0
  248. amsdal/schemas/utils.pyi +10 -0
  249. amsdal/services/__init__.cpython-311-x86_64-linux-gnu.so +0 -0
  250. amsdal/services/__init__.pyi +0 -0
  251. amsdal/services/transaction_execution.cpython-311-x86_64-linux-gnu.so +0 -0
  252. amsdal/services/transaction_execution.pyi +93 -0
  253. amsdal/transactions/__init__.py +13 -0
  254. amsdal/transactions/__init__.pyi +4 -0
  255. amsdal/utils/__init__.py +0 -0
  256. amsdal/utils/__init__.pyi +0 -0
  257. amsdal/utils/contrib_paths.py +23 -0
  258. amsdal/utils/contrib_paths.pyi +14 -0
  259. amsdal/utils/rollback/__init__.py +440 -0
  260. amsdal/utils/rollback/__init__.pyi +38 -0
  261. amsdal/utils/tests/__init__.py +0 -0
  262. amsdal/utils/tests/enums.py +18 -0
  263. amsdal/utils/tests/factories.py +49 -0
  264. amsdal/utils/tests/helpers.py +499 -0
  265. amsdal-0.4.13.dist-info/METADATA +369 -0
  266. amsdal-0.4.13.dist-info/RECORD +269 -0
  267. amsdal-0.4.13.dist-info/WHEEL +6 -0
  268. amsdal-0.4.13.dist-info/licenses/LICENSE.txt +107 -0
  269. amsdal-0.4.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,108 @@
1
+ from _typeshed import Incomplete
2
+ from amsdal.contrib.auth.errors import AuthenticationError as AuthenticationError
3
+ from amsdal_data.transactions.decorators import async_transaction, transaction
4
+ from amsdal_models.classes.model import Model
5
+ from amsdal_utils.lifecycle.consumer import LifecycleConsumer
6
+ from typing import Any
7
+
8
+ logger: Incomplete
9
+
10
+ class CheckAndCreateSuperUserConsumer(LifecycleConsumer):
11
+ """
12
+ Ensures the existence of a super user in the system.
13
+
14
+ This consumer checks if a super user exists based on the provided email and password
15
+ in the authentication settings. If the super user does not exist, it creates one.
16
+ """
17
+ @transaction
18
+ def on_event(self) -> None:
19
+ """
20
+ Checks for the existence of a super user and creates one if necessary.
21
+
22
+ This method ensures that a super user exists by checking the email and password
23
+ in the authentication settings. If the super user does not exist, it creates one
24
+ with the necessary permissions.
25
+ """
26
+ @async_transaction
27
+ async def on_event_async(self) -> None:
28
+ """
29
+ Checks for the existence of a super user and creates one if necessary.
30
+
31
+ This method ensures that a super user exists by checking the email and password
32
+ in the authentication settings. If the super user does not exist, it creates one
33
+ with the necessary permissions.
34
+ """
35
+
36
+ class AuthenticateUserConsumer(LifecycleConsumer):
37
+ """
38
+ Authenticates a user based on a provided JWT token.
39
+
40
+ This consumer decodes the JWT token from the authorization header and retrieves
41
+ the corresponding user from the database. If the token is invalid or expired,
42
+ it raises an `AuthenticationError`.
43
+ """
44
+ def on_event(self, auth_header: str, authentication_info: Any) -> None:
45
+ """
46
+ Authenticates the user using the provided JWT token.
47
+
48
+ This method decodes the JWT token from the authorization header and retrieves
49
+ the corresponding user from the database. If the token is invalid or expired,
50
+ it raises an `AuthenticationError`.
51
+
52
+ Args:
53
+ auth_header (str): The JWT token from the authorization header.
54
+ authentication_info (Any): The authentication information object to update with the user.
55
+ """
56
+ async def on_event_async(self, auth_header: str, authentication_info: Any) -> None:
57
+ """
58
+ Authenticates the user using the provided JWT token.
59
+
60
+ This method decodes the JWT token from the authorization header and retrieves
61
+ the corresponding user from the database. If the token is invalid or expired,
62
+ it raises an `AuthenticationError`.
63
+
64
+ Args:
65
+ auth_header (str): The JWT token from the authorization header.
66
+ authentication_info (Any): The authentication information object to update with the user.
67
+ """
68
+
69
+ class CheckPermissionConsumer(LifecycleConsumer):
70
+ """
71
+ Checks and manages permissions for a given user and object.
72
+
73
+ This consumer prepopulates default permissions, checks class-level permissions,
74
+ and object-level permissions for a given user and object.
75
+ """
76
+ def _prepopulate_default_permissions(self, object_class: type[Model], permissions_info: Any) -> None: ...
77
+ async def _async_prepopulate_default_permissions(self, object_class: type[Model], permissions_info: Any) -> None: ...
78
+ def _check_class_permissions(self, object_class: type[Model], user: Any, permissions_info: Any) -> None: ...
79
+ async def _async_check_class_permissions(self, object_class: type[Model], user: Any, permissions_info: Any) -> None: ...
80
+ def _check_object_permissions(self, obj: Model, user: Any, permissions_info: Any) -> None: ...
81
+ def on_event(self, object_class: type[Model], user: Any, access_types: list[Any], permissions_info: Any, obj: Model | None = None) -> None:
82
+ """
83
+ Main method to check permissions for a given user and object.
84
+
85
+ This method prepopulates default permissions, checks class-level permissions,
86
+ and object-level permissions for the given user and object.
87
+
88
+ Args:
89
+ object_class (type[Model]): The class of the object to check permissions for.
90
+ user (Any): The user to check permissions for.
91
+ access_types (list[Any]): The list of access types to check.
92
+ permissions_info (Any): The permissions information object to update.
93
+ obj (Model | None): The object to check permissions for, if any.
94
+ """
95
+ async def on_event_async(self, object_class: type[Model], user: Any, access_types: list[Any], permissions_info: Any, obj: Model | None = None) -> None:
96
+ """
97
+ Main method to check permissions for a given user and object.
98
+
99
+ This method prepopulates default permissions, checks class-level permissions,
100
+ and object-level permissions for the given user and object.
101
+
102
+ Args:
103
+ object_class (type[Model]): The class of the object to check permissions for.
104
+ user (Any): The user to check permissions for.
105
+ access_types (list[Any]): The list of access types to check.
106
+ permissions_info (Any): The permissions information object to update.
107
+ obj (Model | None): The object to check permissions for, if any.
108
+ """
@@ -0,0 +1,84 @@
1
+ from amsdal_models.migration import migrations
2
+ from amsdal_utils.models.enums import ModuleType
3
+
4
+
5
+ class Migration(migrations.Migration):
6
+ operations: list[migrations.Operation] = [
7
+ migrations.CreateClass(
8
+ module_type=ModuleType.CONTRIB,
9
+ class_name='Permission',
10
+ new_schema={
11
+ 'title': 'Permission',
12
+ 'required': ['model', 'action'],
13
+ 'properties': {
14
+ 'model': {'type': 'string', 'title': 'Model'},
15
+ 'action': {'type': 'string', 'title': 'Action'},
16
+ },
17
+ "primary_key": ["partition_key"],
18
+ "table_name": "Permission",
19
+ 'custom_code': "@property # type: ignore[misc]\ndef display_name(self) -> str: # type: ignore[no-untyped-def]\n return f'{self.model}:{self.action}'",
20
+ },
21
+ ),
22
+ migrations.CreateClass(
23
+ module_type=ModuleType.CONTRIB,
24
+ class_name='User',
25
+ new_schema={
26
+ 'title': 'User',
27
+ 'required': ['email', 'password'],
28
+ 'properties': {
29
+ 'email': {'type': 'string', 'title': 'Email'},
30
+ 'password': {'type': 'binary', 'title': 'Password (hash)'},
31
+ 'permissions': {'type': 'array', 'items': {'type': 'Permission'}, 'title': 'Permissions'},
32
+ },
33
+ "primary_key": ["partition_key"],
34
+ "table_name": "User",
35
+ 'custom_code': "from typing import Any\n\n\ndef pre_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None: # type: ignore[no-untyped-def] # noqa: ARG001\n import bcrypt\n\n from amsdal.contrib.auth.errors import UserCreationError\n\n email = kwargs.get('email', None)\n password = kwargs.get('password', None)\n\n if email is None or email == '':\n msg = \"Email can't be empty\"\n raise UserCreationError(msg)\n\n if password is None or password == '':\n msg = \"Password can't be empty\"\n raise UserCreationError(msg)\n\n kwargs['email'] = email.lower()\n\n if is_new_object and '_metadata' not in kwargs:\n hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())\n kwargs['password'] = hashed_password\n kwargs['_object_id'] = email.lower()\n\ndef pre_create(self) -> None: # type: ignore[no-untyped-def] # noqa: ARG001\n pass\n\n@property # type: ignore[misc]\ndef display_name(self) -> str: # type: ignore[no-untyped-def]\n return self.email",
36
+ },
37
+ ),
38
+ migrations.CreateClass(
39
+ module_type=ModuleType.CONTRIB,
40
+ class_name='UserPermission',
41
+ new_schema={
42
+ 'title': 'UserPermission',
43
+ 'required': ['user', 'permission'],
44
+ 'properties': {
45
+ 'user': {'type': 'User', 'title': 'User', 'db_field': ['user_partition_key']},
46
+ 'permission': {
47
+ 'type': 'Permission',
48
+ 'title': 'Permission',
49
+ 'db_field': ['permission_partition_key'],
50
+ },
51
+ },
52
+ "primary_key": ["user", "permission"],
53
+ "foreign_keys": {
54
+ "user": [
55
+ {"user_partition_key": "string"},
56
+ "User",
57
+ ["partition_key"],
58
+ ],
59
+ "permission": [
60
+ {"permission_partition_key": "string"},
61
+ "Permission",
62
+ ["partition_key"],
63
+ ],
64
+ },
65
+ "table_name": "UserPermission",
66
+ },
67
+ ),
68
+ migrations.CreateClass(
69
+ module_type=ModuleType.CONTRIB,
70
+ class_name='LoginSession',
71
+ new_schema={
72
+ 'title': 'LoginSession',
73
+ 'required': ['email', 'password'],
74
+ 'properties': {
75
+ 'email': {'type': 'string', 'title': 'Email'},
76
+ 'password': {'type': 'string', 'title': 'Password (hash)'},
77
+ 'token': {'type': 'string', 'title': 'Token', 'mark_as_read_only': True},
78
+ },
79
+ "primary_key": ["partition_key"],
80
+ "table_name": "LoginSession",
81
+ 'custom_code': "from datetime import datetime\nfrom datetime import timedelta\nfrom datetime import timezone\nfrom typing import Any\n\nimport bcrypt\nimport jwt\nfrom amsdal_utils.models.enums import Versions\n\n\ndef pre_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None: # type: ignore[no-untyped-def] # noqa: ARG001\n if not is_new_object or '_metadata' in kwargs:\n return\n\n from amsdal.contrib.auth.errors import AuthenticationError\n from amsdal.contrib.auth.settings import auth_settings\n\n email = kwargs.get('email', None)\n password = kwargs.get('password', None)\n\n if not email:\n msg = \"Email can't be empty\"\n raise AuthenticationError(msg)\n\n if not password:\n msg = \"Password can't be empty\"\n raise AuthenticationError(msg)\n\n lowercased_email = email.lower()\n\n from amsdal.contrib.auth.models.user import User # type: ignore[import-not-found]\n\n user = User.objects.filter(email=lowercased_email, _address__object_version=Versions.LATEST).get_or_none().execute()\n\n if not user:\n msg = 'Invalid email / password'\n raise AuthenticationError(msg)\n\n if not bcrypt.checkpw(password.encode('utf-8') if isinstance(password, str) else password, user.password):\n msg = 'Invalid email / password'\n raise AuthenticationError(msg)\n\n kwargs['password'] = 'validated'\n expiration_time = datetime.now(tz=timezone.utc) + timedelta(seconds=1200)\n token = jwt.encode(\n {'email': lowercased_email, 'exp': expiration_time},\n key=auth_settings.AUTH_JWT_KEY, # type: ignore[arg-type]\n algorithm='HS256',\n )\n\n kwargs['token'] = token\n\n@property # type: ignore[misc]\ndef display_name(self) -> str: # type: ignore[no-untyped-def]\n return self.email",
82
+ },
83
+ ),
84
+ ]
File without changes
File without changes
@@ -0,0 +1,118 @@
1
+ from datetime import UTC
2
+ from datetime import datetime
3
+ from datetime import timedelta
4
+ from typing import Any
5
+ from typing import ClassVar
6
+
7
+ import jwt
8
+ from amsdal_models.classes.model import Model
9
+ from amsdal_utils.models.enums import ModuleType
10
+ from pydantic.fields import Field
11
+
12
+
13
+ class LoginSession(Model):
14
+ __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
15
+ email: str = Field(title='Email')
16
+ password: str = Field(title='Password (hash)')
17
+ token: str | None = Field(None, title='Token')
18
+
19
+ @property
20
+ def display_name(self) -> str:
21
+ """
22
+ Returns the display name of the user.
23
+
24
+ This method returns the email of the user as their display name.
25
+
26
+ Returns:
27
+ str: The email of the user.
28
+ """
29
+ return self.email
30
+
31
+ def pre_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None:
32
+ """
33
+ Pre-initializes a user object by validating email and password, and generating a JWT token.
34
+
35
+ This method checks if the object is new and validates the provided email and password.
36
+ If the email and password are valid, it generates a JWT token and adds it to the kwargs.
37
+
38
+ Args:
39
+ is_new_object (bool): Indicates if the object is new.
40
+ kwargs (dict[str, Any]): The keyword arguments containing user details.
41
+
42
+ Raises:
43
+ AuthenticationError: If the email or password is invalid.
44
+ """
45
+ if not is_new_object or '_metadata' in kwargs:
46
+ return
47
+ from amsdal.contrib.auth.errors import AuthenticationError
48
+ from amsdal.contrib.auth.settings import auth_settings
49
+
50
+ email = kwargs.get('email', None)
51
+ password = kwargs.get('password', None)
52
+ if not email:
53
+ msg = "Email can't be empty"
54
+ raise AuthenticationError(msg)
55
+ if not password:
56
+ msg = "Password can't be empty"
57
+ raise AuthenticationError(msg)
58
+ lowercased_email = email.lower()
59
+
60
+ if not auth_settings.AUTH_JWT_KEY:
61
+ msg = 'JWT key is not set'
62
+ raise AuthenticationError(msg)
63
+
64
+ expiration_time = datetime.now(tz=UTC) + timedelta(seconds=auth_settings.AUTH_TOKEN_EXPIRATION)
65
+ token = jwt.encode(
66
+ {'email': lowercased_email, 'exp': expiration_time},
67
+ key=auth_settings.AUTH_JWT_KEY, # type: ignore[arg-type]
68
+ algorithm='HS256',
69
+ )
70
+ kwargs['token'] = token
71
+
72
+ def pre_create(self) -> None:
73
+ import bcrypt
74
+
75
+ from amsdal.contrib.auth.errors import AuthenticationError
76
+ from amsdal.contrib.auth.models.user import User
77
+
78
+ user = User.objects.filter(email=self.email).latest().first().execute()
79
+
80
+ if not user:
81
+ msg = 'User not found'
82
+ raise AuthenticationError(msg)
83
+
84
+ if not bcrypt.checkpw(self.password.encode(), user.password):
85
+ msg = 'Invalid password'
86
+ raise AuthenticationError(msg)
87
+
88
+ self.password = 'validated'
89
+
90
+ def pre_update(self) -> None:
91
+ from amsdal.contrib.auth.errors import AuthenticationError
92
+
93
+ msg = 'Update not allowed'
94
+ raise AuthenticationError(msg)
95
+
96
+ async def apre_create(self) -> None:
97
+ import bcrypt
98
+
99
+ from amsdal.contrib.auth.errors import AuthenticationError
100
+ from amsdal.contrib.auth.models.user import User
101
+
102
+ user = await User.objects.filter(email=self.email).latest().first().aexecute()
103
+
104
+ if not user:
105
+ msg = 'User not found'
106
+ raise AuthenticationError(msg)
107
+
108
+ if not bcrypt.checkpw(self.password.encode(), user.password):
109
+ msg = 'Invalid password'
110
+ raise AuthenticationError(msg)
111
+
112
+ self.password = 'validated'
113
+
114
+ async def apre_update(self) -> None:
115
+ from amsdal.contrib.auth.errors import AuthenticationError
116
+
117
+ msg = 'Update not allowed'
118
+ raise AuthenticationError(msg)
@@ -0,0 +1,37 @@
1
+ from amsdal_models.classes.model import Model
2
+ from amsdal_utils.models.enums import ModuleType
3
+ from typing import Any, ClassVar
4
+
5
+ class LoginSession(Model):
6
+ __module_type__: ClassVar[ModuleType] = ...
7
+ email: str = ...
8
+ password: str = ...
9
+ token: str | None = ...
10
+ @property
11
+ def display_name(self) -> str:
12
+ """
13
+ Returns the display name of the user.
14
+
15
+ This method returns the email of the user as their display name.
16
+
17
+ Returns:
18
+ str: The email of the user.
19
+ """
20
+ def pre_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None:
21
+ """
22
+ Pre-initializes a user object by validating email and password, and generating a JWT token.
23
+
24
+ This method checks if the object is new and validates the provided email and password.
25
+ If the email and password are valid, it generates a JWT token and adds it to the kwargs.
26
+
27
+ Args:
28
+ is_new_object (bool): Indicates if the object is new.
29
+ kwargs (dict[str, Any]): The keyword arguments containing user details.
30
+
31
+ Raises:
32
+ AuthenticationError: If the email or password is invalid.
33
+ """
34
+ def pre_create(self) -> None: ...
35
+ def pre_update(self) -> None: ...
36
+ async def apre_create(self) -> None: ...
37
+ async def apre_update(self) -> None: ...
@@ -0,0 +1,23 @@
1
+ from typing import ClassVar
2
+
3
+ from amsdal_models.classes.model import Model
4
+ from amsdal_utils.models.enums import ModuleType
5
+ from pydantic.fields import Field
6
+
7
+
8
+ class Permission(Model):
9
+ __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
10
+ model: str = Field(title='Model')
11
+ action: str = Field(title='Action')
12
+
13
+ @property
14
+ def display_name(self) -> str:
15
+ """
16
+ Returns the display name of the user.
17
+
18
+ This method returns a formatted string combining the model and action of the user.
19
+
20
+ Returns:
21
+ str: The formatted display name in the format 'model:action'.
22
+ """
23
+ return f'{self.model}:{self.action}'
@@ -0,0 +1,18 @@
1
+ from amsdal_models.classes.model import Model
2
+ from amsdal_utils.models.enums import ModuleType
3
+ from typing import ClassVar
4
+
5
+ class Permission(Model):
6
+ __module_type__: ClassVar[ModuleType] = ...
7
+ model: str = ...
8
+ action: str = ...
9
+ @property
10
+ def display_name(self) -> str:
11
+ """
12
+ Returns the display name of the user.
13
+
14
+ This method returns a formatted string combining the model and action of the user.
15
+
16
+ Returns:
17
+ str: The formatted display name in the format 'model:action'.
18
+ """
@@ -0,0 +1,106 @@
1
+ from typing import Any
2
+ from typing import ClassVar
3
+
4
+ from amsdal_models.classes.model import Model
5
+ from amsdal_utils.models.enums import ModuleType
6
+ from pydantic.fields import Field
7
+
8
+ from amsdal.contrib.auth.models.permission import * # noqa: F403
9
+
10
+
11
+ class User(Model):
12
+ __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
13
+ email: str = Field(title='Email')
14
+ password: bytes = Field(title='Password (hash)')
15
+ permissions: list['Permission'] | None = Field(None, title='Permissions') # noqa: F405
16
+
17
+ def __repr__(self) -> str:
18
+ return str(self)
19
+
20
+ def __str__(self) -> str:
21
+ return f'User(email={self.email})'
22
+
23
+ async def apre_update(self) -> None:
24
+ import bcrypt
25
+
26
+ original_object = await self.arefetch_from_db()
27
+ password = self.password
28
+ if original_object.password and password is not None:
29
+ if isinstance(password, str):
30
+ password = password.encode('utf-8')
31
+ try:
32
+ if not bcrypt.checkpw(password, original_object.password):
33
+ self.password = password
34
+ except ValueError:
35
+ hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
36
+ self.password = hashed_password
37
+
38
+ @property
39
+ def display_name(self) -> str:
40
+ """
41
+ Returns the display name of the user.
42
+
43
+ This method returns the email of the user as their display name.
44
+
45
+ Returns:
46
+ str: The email of the user.
47
+ """
48
+ return self.email
49
+
50
+ def post_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None:
51
+ """
52
+ Post-initializes a user object by validating email and password, and hashing the password.
53
+
54
+ This method checks if the email and password are provided and valid. If the object is new,
55
+ it hashes the password and sets the object ID to the lowercased email.
56
+
57
+ Args:
58
+ is_new_object (bool): Indicates if the object is new.
59
+ kwargs (dict[str, Any]): The keyword arguments containing user details.
60
+
61
+ Raises:
62
+ UserCreationError: If the email or password is invalid.
63
+ """
64
+ import bcrypt
65
+
66
+ from amsdal.contrib.auth.errors import UserCreationError
67
+
68
+ email = kwargs.get('email', None)
69
+ password = kwargs.get('password', None)
70
+ if email is None or email == '':
71
+ msg = "Email can't be empty"
72
+ raise UserCreationError(msg)
73
+ if password is None or password == '':
74
+ msg = "Password can't be empty"
75
+ raise UserCreationError(msg)
76
+ kwargs['email'] = email.lower()
77
+ if is_new_object and '_metadata' not in kwargs:
78
+ if isinstance(password, str):
79
+ password = password.encode('utf-8')
80
+ hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
81
+ self.password = hashed_password
82
+ self._object_id = email.lower()
83
+
84
+ def pre_create(self) -> None:
85
+ """
86
+ Pre-creates a user object.
87
+
88
+ This method is a placeholder for any pre-creation logic that needs to be executed
89
+ before a user object is created.
90
+ """
91
+ pass
92
+
93
+ def pre_update(self) -> None:
94
+ import bcrypt
95
+
96
+ original_object = self.refetch_from_db()
97
+ password = self.password
98
+ if original_object.password and password is not None:
99
+ if isinstance(password, str):
100
+ password = password.encode('utf-8')
101
+ try:
102
+ if not bcrypt.checkpw(password, original_object.password):
103
+ self.password = password
104
+ except ValueError:
105
+ hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
106
+ self.password = hashed_password
@@ -0,0 +1,46 @@
1
+ from amsdal.contrib.auth.models.permission import *
2
+ from amsdal_models.classes.model import Model
3
+ from amsdal_utils.models.enums import ModuleType
4
+ from typing import Any, ClassVar
5
+
6
+ class User(Model):
7
+ __module_type__: ClassVar[ModuleType] = ...
8
+ email: str = ...
9
+ password: bytes = ...
10
+ permissions: list['Permission'] | None = ...
11
+ def __repr__(self) -> str: ...
12
+ def __str__(self) -> str: ...
13
+ async def apre_update(self) -> None: ...
14
+ @property
15
+ def display_name(self) -> str:
16
+ """
17
+ Returns the display name of the user.
18
+
19
+ This method returns the email of the user as their display name.
20
+
21
+ Returns:
22
+ str: The email of the user.
23
+ """
24
+ _object_id = ...
25
+ def post_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None:
26
+ """
27
+ Post-initializes a user object by validating email and password, and hashing the password.
28
+
29
+ This method checks if the email and password are provided and valid. If the object is new,
30
+ it hashes the password and sets the object ID to the lowercased email.
31
+
32
+ Args:
33
+ is_new_object (bool): Indicates if the object is new.
34
+ kwargs (dict[str, Any]): The keyword arguments containing user details.
35
+
36
+ Raises:
37
+ UserCreationError: If the email or password is invalid.
38
+ """
39
+ def pre_create(self) -> None:
40
+ """
41
+ Pre-creates a user object.
42
+
43
+ This method is a placeholder for any pre-creation logic that needs to be executed
44
+ before a user object is created.
45
+ """
46
+ def pre_update(self) -> None: ...
@@ -0,0 +1,36 @@
1
+ from pydantic_settings import BaseSettings
2
+ from pydantic_settings import SettingsConfigDict
3
+
4
+
5
+ class Settings(BaseSettings):
6
+ """
7
+ Settings configuration for the application.
8
+
9
+ This class uses Pydantic's BaseSettings to manage application settings
10
+ from environment variables and a .env file.
11
+
12
+ Attributes:
13
+ model_config (SettingsConfigDict): Configuration for Pydantic settings.
14
+ ADMIN_USER_EMAIL (str | None): The email of the admin user.
15
+ ADMIN_USER_PASSWORD (str | None): The password of the admin user.
16
+ AUTH_JWT_KEY (str | None): The key used for JWT authentication.
17
+ AUTH_TOKEN_EXPIRATION (int): The expiration time for authentication tokens in seconds.
18
+ REQUIRE_DEFAULT_AUTHORIZATION (bool): Flag to require default authorization.
19
+ """
20
+
21
+ model_config = SettingsConfigDict(
22
+ case_sensitive=True,
23
+ env_prefix='AMSDAL_',
24
+ env_file='.env',
25
+ env_file_encoding='utf-8',
26
+ extra='ignore',
27
+ )
28
+
29
+ ADMIN_USER_EMAIL: str | None = None
30
+ ADMIN_USER_PASSWORD: str | None = None
31
+ AUTH_JWT_KEY: str | None = None
32
+ AUTH_TOKEN_EXPIRATION: int = 86400
33
+ REQUIRE_DEFAULT_AUTHORIZATION: bool = True
34
+
35
+
36
+ auth_settings = Settings()
@@ -0,0 +1,26 @@
1
+ from _typeshed import Incomplete
2
+ from pydantic_settings import BaseSettings
3
+
4
+ class Settings(BaseSettings):
5
+ """
6
+ Settings configuration for the application.
7
+
8
+ This class uses Pydantic's BaseSettings to manage application settings
9
+ from environment variables and a .env file.
10
+
11
+ Attributes:
12
+ model_config (SettingsConfigDict): Configuration for Pydantic settings.
13
+ ADMIN_USER_EMAIL (str | None): The email of the admin user.
14
+ ADMIN_USER_PASSWORD (str | None): The password of the admin user.
15
+ AUTH_JWT_KEY (str | None): The key used for JWT authentication.
16
+ AUTH_TOKEN_EXPIRATION (int): The expiration time for authentication tokens in seconds.
17
+ REQUIRE_DEFAULT_AUTHORIZATION (bool): Flag to require default authorization.
18
+ """
19
+ model_config: Incomplete
20
+ ADMIN_USER_EMAIL: str | None
21
+ ADMIN_USER_PASSWORD: str | None
22
+ AUTH_JWT_KEY: str | None
23
+ AUTH_TOKEN_EXPIRATION: int
24
+ REQUIRE_DEFAULT_AUTHORIZATION: bool
25
+
26
+ auth_settings: Incomplete
File without changes
File without changes
@@ -0,0 +1,24 @@
1
+ from amsdal_utils.lifecycle.producer import LifecycleProducer
2
+
3
+ from amsdal.contrib.app_config import AppConfig
4
+ from amsdal.contrib.frontend_configs.constants import ON_RESPONSE_EVENT
5
+ from amsdal.contrib.frontend_configs.lifecycle.consumer import ProcessResponseConsumer
6
+
7
+
8
+ class FrontendConfigAppConfig(AppConfig):
9
+ """
10
+ Application configuration class for frontend configurations.
11
+
12
+ This class extends the AppConfig and sets up listeners for lifecycle events
13
+ to process frontend configurations.
14
+ """
15
+
16
+ def on_ready(self) -> None:
17
+ """
18
+ Registers a listener for the ON_RESPONSE_EVENT to process responses
19
+ using the ProcessResponseConsumer.
20
+
21
+ Returns:
22
+ None
23
+ """
24
+ LifecycleProducer.add_listener(ON_RESPONSE_EVENT, ProcessResponseConsumer) # type: ignore[arg-type]
@@ -0,0 +1,19 @@
1
+ from amsdal.contrib.app_config import AppConfig as AppConfig
2
+ from amsdal.contrib.frontend_configs.constants import ON_RESPONSE_EVENT as ON_RESPONSE_EVENT
3
+ from amsdal.contrib.frontend_configs.lifecycle.consumer import ProcessResponseConsumer as ProcessResponseConsumer
4
+
5
+ class FrontendConfigAppConfig(AppConfig):
6
+ """
7
+ Application configuration class for frontend configurations.
8
+
9
+ This class extends the AppConfig and sets up listeners for lifecycle events
10
+ to process frontend configurations.
11
+ """
12
+ def on_ready(self) -> None:
13
+ """
14
+ Registers a listener for the ON_RESPONSE_EVENT to process responses
15
+ using the ProcessResponseConsumer.
16
+
17
+ Returns:
18
+ None
19
+ """
@@ -0,0 +1 @@
1
+ ON_RESPONSE_EVENT = 'on_response'