dmart 1.4.40.post8__py3-none-any.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 (489) hide show
  1. dmart/__init__.py +7 -0
  2. dmart/alembic/README +1 -0
  3. dmart/alembic/__init__.py +0 -0
  4. dmart/alembic/env.py +91 -0
  5. dmart/alembic/notes.txt +11 -0
  6. dmart/alembic/script.py.mako +28 -0
  7. dmart/alembic/scripts/__init__.py +0 -0
  8. dmart/alembic/scripts/calculate_checksums.py +77 -0
  9. dmart/alembic/scripts/migration_f7a4949eed19.py +28 -0
  10. dmart/alembic/versions/0f3d2b1a7c21_add_authz_materialized_views.py +87 -0
  11. dmart/alembic/versions/10d2041b94d4_last_checksum_history.py +62 -0
  12. dmart/alembic/versions/1cf4e1ee3cb8_ext_permission_with_filter_fields_values.py +33 -0
  13. dmart/alembic/versions/26bfe19b49d4_rm_failedloginattempts.py +42 -0
  14. dmart/alembic/versions/3c8bca2219cc_add_otp_table.py +38 -0
  15. dmart/alembic/versions/6675fd9dfe42_remove_unique_from_sessions_table.py +36 -0
  16. dmart/alembic/versions/71bc1df82e6a_adding_user_last_login_at.py +43 -0
  17. dmart/alembic/versions/74288ccbd3b5_initial.py +264 -0
  18. dmart/alembic/versions/7520a89a8467_rm_activesession_table.py +39 -0
  19. dmart/alembic/versions/848b623755a4_make_created_nd_updated_at_required.py +138 -0
  20. dmart/alembic/versions/8640dcbebf85_add_notes_to_users.py +32 -0
  21. dmart/alembic/versions/91c94250232a_adding_fk_on_owner_shortname.py +104 -0
  22. dmart/alembic/versions/98ecd6f56f9a_ext_meta_with_owner_group_shortname.py +66 -0
  23. dmart/alembic/versions/9aae9138c4ef_indexing_created_at_updated_at.py +80 -0
  24. dmart/alembic/versions/__init__.py +0 -0
  25. dmart/alembic/versions/b53f916b3f6d_json_to_jsonb.py +492 -0
  26. dmart/alembic/versions/eb5f1ec65156_adding_user_locked_to_device.py +36 -0
  27. dmart/alembic/versions/f7a4949eed19_adding_query_policies_to_meta.py +60 -0
  28. dmart/alembic.ini +117 -0
  29. dmart/api/__init__.py +0 -0
  30. dmart/api/info/__init__.py +0 -0
  31. dmart/api/info/router.py +109 -0
  32. dmart/api/managed/__init__.py +0 -0
  33. dmart/api/managed/router.py +1541 -0
  34. dmart/api/managed/utils.py +1879 -0
  35. dmart/api/public/__init__.py +0 -0
  36. dmart/api/public/router.py +758 -0
  37. dmart/api/qr/__init__.py +0 -0
  38. dmart/api/qr/router.py +108 -0
  39. dmart/api/user/__init__.py +0 -0
  40. dmart/api/user/model/__init__.py +0 -0
  41. dmart/api/user/model/errors.py +14 -0
  42. dmart/api/user/model/requests.py +165 -0
  43. dmart/api/user/model/responses.py +11 -0
  44. dmart/api/user/router.py +1413 -0
  45. dmart/api/user/service.py +270 -0
  46. dmart/bundler.py +52 -0
  47. dmart/cli.py +1133 -0
  48. dmart/config/__init__.py +0 -0
  49. dmart/config/channels.json +11 -0
  50. dmart/config/notification.json +17 -0
  51. dmart/config.env.sample +27 -0
  52. dmart/config.ini.sample +7 -0
  53. dmart/conftest.py +13 -0
  54. dmart/curl.sh +196 -0
  55. dmart/cxb/__init__.py +0 -0
  56. dmart/cxb/assets/@codemirror-Rn7_6DkE.js +10 -0
  57. dmart/cxb/assets/@edraj-CS4NwVbD.js +1 -0
  58. dmart/cxb/assets/@floating-ui-BwwcF-xh.js +1 -0
  59. dmart/cxb/assets/@formatjs-yKEsAtjs.js +1 -0
  60. dmart/cxb/assets/@fortawesome-DRW1UCdr.js +9 -0
  61. dmart/cxb/assets/@jsonquerylang-laKNoFFq.js +12 -0
  62. dmart/cxb/assets/@lezer-za4Q-8Ew.js +1 -0
  63. dmart/cxb/assets/@marijn-DXwl3gUT.js +1 -0
  64. dmart/cxb/assets/@popperjs-l0sNRNKZ.js +1 -0
  65. dmart/cxb/assets/@replit--ERk53eB.js +1 -0
  66. dmart/cxb/assets/@roxi-CGMFK4i8.js +6 -0
  67. dmart/cxb/assets/@typewriter-cCzskkIv.js +17 -0
  68. dmart/cxb/assets/@zerodevx-BlBZjKxu.js +1 -0
  69. dmart/cxb/assets/@zerodevx-CVEpe6WZ.css +1 -0
  70. dmart/cxb/assets/BreadCrumbLite-DAhOx38v.js +1 -0
  71. dmart/cxb/assets/EntryRenderer-CCqV8Rkg.js +32 -0
  72. dmart/cxb/assets/EntryRenderer-DXytdFp9.css +1 -0
  73. dmart/cxb/assets/ListView-BQelo7vZ.js +16 -0
  74. dmart/cxb/assets/ListView-U8of-_c-.css +1 -0
  75. dmart/cxb/assets/Prism--hMplq-p.js +3 -0
  76. dmart/cxb/assets/Prism-Uh6uStUw.css +1 -0
  77. dmart/cxb/assets/Table2Cols-BsbwicQm.js +1 -0
  78. dmart/cxb/assets/_..-BvT6vdHa.css +1 -0
  79. dmart/cxb/assets/_...404_-fuLH_rX9.js +2 -0
  80. dmart/cxb/assets/_...fallback_-Ba_NLmAE.js +1 -0
  81. dmart/cxb/assets/_module-3HrtKAWo.js +3 -0
  82. dmart/cxb/assets/_module-DFKFq0AM.js +4 -0
  83. dmart/cxb/assets/_module-Dgq0ZVtz.js +1 -0
  84. dmart/cxb/assets/ajv-Cpj98o6Y.js +1 -0
  85. dmart/cxb/assets/axios-CG2WSiiR.js +6 -0
  86. dmart/cxb/assets/clsx-B-dksMZM.js +1 -0
  87. dmart/cxb/assets/codemirror-wrapped-line-indent-DPhKvljI.js +1 -0
  88. dmart/cxb/assets/compare-C3AjiGFR.js +1 -0
  89. dmart/cxb/assets/compute-scroll-into-view-Bl8rNFhg.js +1 -0
  90. dmart/cxb/assets/consolite-DlCuI0F9.js +1 -0
  91. dmart/cxb/assets/crelt-C8TCjufn.js +1 -0
  92. dmart/cxb/assets/date-fns-l0sNRNKZ.js +1 -0
  93. dmart/cxb/assets/deepmerge-rn4rBaHU.js +1 -0
  94. dmart/cxb/assets/dmart_services-AL6-IdDE.js +1 -0
  95. dmart/cxb/assets/downloadFile-D08i0YDh.js +1 -0
  96. dmart/cxb/assets/easy-signal-BiPFIK3O.js +1 -0
  97. dmart/cxb/assets/esm-env-rsSWfq8L.js +1 -0
  98. dmart/cxb/assets/export-OF_rTiXu.js +1 -0
  99. dmart/cxb/assets/fast-deep-equal-l0sNRNKZ.js +1 -0
  100. dmart/cxb/assets/fast-diff-C-IidNf4.js +1 -0
  101. dmart/cxb/assets/fast-uri-l0sNRNKZ.js +1 -0
  102. dmart/cxb/assets/flowbite-svelte-BLvjb-sa.js +1 -0
  103. dmart/cxb/assets/flowbite-svelte-CD54FDqW.css +1 -0
  104. dmart/cxb/assets/flowbite-svelte-icons-BI8GVhw_.js +1 -0
  105. dmart/cxb/assets/github-slugger-CQ4oX9Ud.js +1 -0
  106. dmart/cxb/assets/global-igKv-1g9.js +1 -0
  107. dmart/cxb/assets/hookar-BMRD9G9H.js +1 -0
  108. dmart/cxb/assets/immutable-json-patch-DtRO2E_S.js +1 -0
  109. dmart/cxb/assets/import-1vE3gBat.js +1 -0
  110. dmart/cxb/assets/index-B-eTh-ZX.js +1 -0
  111. dmart/cxb/assets/index-BSsK-X71.js +1 -0
  112. dmart/cxb/assets/index-BVyxzKtH.js +1 -0
  113. dmart/cxb/assets/index-BdeNM69f.js +1 -0
  114. dmart/cxb/assets/index-CC-A1ipE.js +1 -0
  115. dmart/cxb/assets/index-CQohGiYB.js +1 -0
  116. dmart/cxb/assets/index-ChjnkpdZ.js +4 -0
  117. dmart/cxb/assets/index-DLP7csA4.js +1 -0
  118. dmart/cxb/assets/index-DTfhnhwd.js +1 -0
  119. dmart/cxb/assets/index-DdXRK7n9.js +2 -0
  120. dmart/cxb/assets/index-DtiCmB4o.js +1 -0
  121. dmart/cxb/assets/index-NBrXBlLA.css +2 -0
  122. dmart/cxb/assets/index-X1uNehO7.js +1 -0
  123. dmart/cxb/assets/index-nrQW6Nrr.js +1 -0
  124. dmart/cxb/assets/info-B986lRiM.js +1 -0
  125. dmart/cxb/assets/intl-messageformat-Dc5UU-HB.js +3 -0
  126. dmart/cxb/assets/jmespath-l0sNRNKZ.js +1 -0
  127. dmart/cxb/assets/json-schema-traverse-l0sNRNKZ.js +1 -0
  128. dmart/cxb/assets/json-source-map-DRgZidqy.js +5 -0
  129. dmart/cxb/assets/jsonpath-plus-l0sNRNKZ.js +1 -0
  130. dmart/cxb/assets/jsonrepair-B30Dx381.js +8 -0
  131. dmart/cxb/assets/lodash-es-DZVAA2ox.js +1 -0
  132. dmart/cxb/assets/marked-DKjyhwJX.js +56 -0
  133. dmart/cxb/assets/marked-gfm-heading-id-U5zO829x.js +2 -0
  134. dmart/cxb/assets/marked-mangle-CDMeiHC6.js +1 -0
  135. dmart/cxb/assets/memoize-one-BdPwpGay.js +1 -0
  136. dmart/cxb/assets/natural-compare-lite-Bg2Xcf-o.js +7 -0
  137. dmart/cxb/assets/pagination-svelte-D5CyoiE_.js +13 -0
  138. dmart/cxb/assets/pagination-svelte-v10nAbbM.css +1 -0
  139. dmart/cxb/assets/plantuml-encoder-C47mzt9T.js +1 -0
  140. dmart/cxb/assets/prismjs-DTUiLGJu.js +9 -0
  141. dmart/cxb/assets/profile-BUf-tKMe.js +1 -0
  142. dmart/cxb/assets/query-CNmXTsgf.js +1 -0
  143. dmart/cxb/assets/queryHelpers-C9iBWwqe.js +1 -0
  144. dmart/cxb/assets/scroll-into-view-if-needed-KR58zyjF.js +1 -0
  145. dmart/cxb/assets/spaces-0oyGvpii.js +1 -0
  146. dmart/cxb/assets/style-mod-Bs6eFhZE.js +3 -0
  147. dmart/cxb/assets/svelte-B2XmcTi_.js +4 -0
  148. dmart/cxb/assets/svelte-awesome-COLlx0DN.css +1 -0
  149. dmart/cxb/assets/svelte-awesome-DhnMA6Q_.js +1 -0
  150. dmart/cxb/assets/svelte-datatables-net-CY7LBj6I.js +1 -0
  151. dmart/cxb/assets/svelte-floating-ui-BlS3sOAQ.js +1 -0
  152. dmart/cxb/assets/svelte-i18n-CT2KkQaN.js +3 -0
  153. dmart/cxb/assets/svelte-jsoneditor-BzfX6Usi.css +1 -0
  154. dmart/cxb/assets/svelte-jsoneditor-CUGSvWId.js +25 -0
  155. dmart/cxb/assets/svelte-select-CegQKzqH.css +1 -0
  156. dmart/cxb/assets/svelte-select-CjHAt_85.js +6 -0
  157. dmart/cxb/assets/tailwind-merge-CJvxXMcu.js +1 -0
  158. dmart/cxb/assets/tailwind-variants-Cj20BoQ3.js +1 -0
  159. dmart/cxb/assets/toast-B9WDyfyI.js +1 -0
  160. dmart/cxb/assets/tslib-pJfR_DrR.js +1 -0
  161. dmart/cxb/assets/typewriter-editor-DkTVIJdm.js +25 -0
  162. dmart/cxb/assets/user-DeK_NB5v.js +1 -0
  163. dmart/cxb/assets/vanilla-picker-l5rcX3cq.js +8 -0
  164. dmart/cxb/assets/w3c-keyname-Vcq4gwWv.js +1 -0
  165. dmart/cxb/config.json +11 -0
  166. dmart/cxb/config.sample.json +11 -0
  167. dmart/cxb/favicon.ico +0 -0
  168. dmart/cxb/favicon.png +0 -0
  169. dmart/cxb/index.html +28 -0
  170. dmart/data_adapters/__init__.py +0 -0
  171. dmart/data_adapters/adapter.py +16 -0
  172. dmart/data_adapters/base_data_adapter.py +467 -0
  173. dmart/data_adapters/file/__init__.py +0 -0
  174. dmart/data_adapters/file/adapter.py +2043 -0
  175. dmart/data_adapters/file/adapter_helpers.py +1013 -0
  176. dmart/data_adapters/file/archive.py +150 -0
  177. dmart/data_adapters/file/create_index.py +331 -0
  178. dmart/data_adapters/file/create_users_folders.py +52 -0
  179. dmart/data_adapters/file/custom_validations.py +68 -0
  180. dmart/data_adapters/file/drop_index.py +40 -0
  181. dmart/data_adapters/file/health_check.py +560 -0
  182. dmart/data_adapters/file/redis_services.py +1110 -0
  183. dmart/data_adapters/helpers.py +27 -0
  184. dmart/data_adapters/sql/__init__.py +0 -0
  185. dmart/data_adapters/sql/adapter.py +3218 -0
  186. dmart/data_adapters/sql/adapter_helpers.py +491 -0
  187. dmart/data_adapters/sql/create_tables.py +451 -0
  188. dmart/data_adapters/sql/create_users_folders.py +53 -0
  189. dmart/data_adapters/sql/db_to_json_migration.py +485 -0
  190. dmart/data_adapters/sql/health_check_sql.py +232 -0
  191. dmart/data_adapters/sql/json_to_db_migration.py +454 -0
  192. dmart/data_adapters/sql/update_query_policies.py +101 -0
  193. dmart/data_generator.py +81 -0
  194. dmart/dmart.py +761 -0
  195. dmart/get_settings.py +7 -0
  196. dmart/hypercorn_config.toml +3 -0
  197. dmart/info.json +1 -0
  198. dmart/languages/__init__.py +0 -0
  199. dmart/languages/arabic.json +15 -0
  200. dmart/languages/english.json +16 -0
  201. dmart/languages/kurdish.json +14 -0
  202. dmart/languages/loader.py +12 -0
  203. dmart/login_creds.sh +7 -0
  204. dmart/login_creds.sh.sample +7 -0
  205. dmart/main.py +563 -0
  206. dmart/manifest.sh +12 -0
  207. dmart/migrate.py +24 -0
  208. dmart/models/__init__.py +0 -0
  209. dmart/models/api.py +203 -0
  210. dmart/models/core.py +597 -0
  211. dmart/models/enums.py +255 -0
  212. dmart/password_gen.py +8 -0
  213. dmart/plugins/__init__.py +0 -0
  214. dmart/plugins/action_log/__init__.py +0 -0
  215. dmart/plugins/action_log/config.json +13 -0
  216. dmart/plugins/action_log/plugin.py +121 -0
  217. dmart/plugins/admin_notification_sender/__init__.py +0 -0
  218. dmart/plugins/admin_notification_sender/config.json +13 -0
  219. dmart/plugins/admin_notification_sender/plugin.py +124 -0
  220. dmart/plugins/ldap_manager/__init__.py +0 -0
  221. dmart/plugins/ldap_manager/config.json +12 -0
  222. dmart/plugins/ldap_manager/dmart.schema +146 -0
  223. dmart/plugins/ldap_manager/plugin.py +100 -0
  224. dmart/plugins/ldap_manager/slapd.conf +53 -0
  225. dmart/plugins/local_notification/__init__.py +0 -0
  226. dmart/plugins/local_notification/config.json +13 -0
  227. dmart/plugins/local_notification/plugin.py +123 -0
  228. dmart/plugins/realtime_updates_notifier/__init__.py +0 -0
  229. dmart/plugins/realtime_updates_notifier/config.json +12 -0
  230. dmart/plugins/realtime_updates_notifier/plugin.py +58 -0
  231. dmart/plugins/redis_db_update/__init__.py +0 -0
  232. dmart/plugins/redis_db_update/config.json +13 -0
  233. dmart/plugins/redis_db_update/plugin.py +188 -0
  234. dmart/plugins/resource_folders_creation/__init__.py +0 -0
  235. dmart/plugins/resource_folders_creation/config.json +12 -0
  236. dmart/plugins/resource_folders_creation/plugin.py +81 -0
  237. dmart/plugins/system_notification_sender/__init__.py +0 -0
  238. dmart/plugins/system_notification_sender/config.json +13 -0
  239. dmart/plugins/system_notification_sender/plugin.py +188 -0
  240. dmart/plugins/update_access_controls/__init__.py +0 -0
  241. dmart/plugins/update_access_controls/config.json +12 -0
  242. dmart/plugins/update_access_controls/plugin.py +9 -0
  243. dmart/publish.sh +57 -0
  244. dmart/pylint.sh +16 -0
  245. dmart/pyrightconfig.json +7 -0
  246. dmart/redis_connections.sh +13 -0
  247. dmart/reload.sh +56 -0
  248. dmart/run.sh +3 -0
  249. dmart/run_notification_campaign.py +85 -0
  250. dmart/sample/spaces/applications/.dm/meta.space.json +30 -0
  251. dmart/sample/spaces/applications/api/.dm/meta.folder.json +1 -0
  252. dmart/sample/spaces/applications/api/.dm/query_all_applications/meta.content.json +1 -0
  253. dmart/sample/spaces/applications/api/.dm/test_by_saad/attachments.media/meta.warframe.json +1 -0
  254. dmart/sample/spaces/applications/api/.dm/test_by_saad/attachments.media/warframe.png +0 -0
  255. dmart/sample/spaces/applications/api/.dm/test_by_saad/meta.content.json +1 -0
  256. dmart/sample/spaces/applications/api/.dm/user_profile/meta.content.json +1 -0
  257. dmart/sample/spaces/applications/api/applications/.dm/create_log/meta.content.json +1 -0
  258. dmart/sample/spaces/applications/api/applications/.dm/create_public_logs/meta.content.json +1 -0
  259. dmart/sample/spaces/applications/api/applications/.dm/meta.folder.json +1 -0
  260. dmart/sample/spaces/applications/api/applications/.dm/query_all_translated_data/meta.content.json +1 -0
  261. dmart/sample/spaces/applications/api/applications/.dm/query_logs/meta.content.json +1 -0
  262. dmart/sample/spaces/applications/api/applications/.dm/query_translated_enums/meta.content.json +1 -0
  263. dmart/sample/spaces/applications/api/applications/.dm/query_translated_others/meta.content.json +1 -0
  264. dmart/sample/spaces/applications/api/applications/.dm/query_translated_resolution/meta.content.json +1 -0
  265. dmart/sample/spaces/applications/api/applications/create_log.json +1 -0
  266. dmart/sample/spaces/applications/api/applications/create_public_logs.json +1 -0
  267. dmart/sample/spaces/applications/api/applications/query_all_translated_data.json +1 -0
  268. dmart/sample/spaces/applications/api/applications/query_logs.json +1 -0
  269. dmart/sample/spaces/applications/api/applications/query_translated_enums.json +1 -0
  270. dmart/sample/spaces/applications/api/applications/query_translated_others.json +1 -0
  271. dmart/sample/spaces/applications/api/applications/query_translated_resolution.json +1 -0
  272. dmart/sample/spaces/applications/api/applications.json +1 -0
  273. dmart/sample/spaces/applications/api/management/.dm/create_subaccount/meta.content.json +1 -0
  274. dmart/sample/spaces/applications/api/management/.dm/meta.folder.json +1 -0
  275. dmart/sample/spaces/applications/api/management/.dm/update_password/meta.content.json +1 -0
  276. dmart/sample/spaces/applications/api/management/create_subaccount.json +53 -0
  277. dmart/sample/spaces/applications/api/management/update_password.json +1 -0
  278. dmart/sample/spaces/applications/api/management.json +1 -0
  279. dmart/sample/spaces/applications/api/query_all_applications.json +15 -0
  280. dmart/sample/spaces/applications/api/test_by_saad.json +1 -0
  281. dmart/sample/spaces/applications/api/user/.dm/meta.folder.json +1 -0
  282. dmart/sample/spaces/applications/api/user/.dm/test_by_saad/meta.content.json +1 -0
  283. dmart/sample/spaces/applications/api/user/.dm/user_profile/meta.content.json +1 -0
  284. dmart/sample/spaces/applications/api/user/test_by_saad.json +1 -0
  285. dmart/sample/spaces/applications/api/user/user_profile.json +1 -0
  286. dmart/sample/spaces/applications/api/user_profile.json +1 -0
  287. dmart/sample/spaces/applications/api.json +1 -0
  288. dmart/sample/spaces/applications/collections/.dm/meta.folder.json +19 -0
  289. dmart/sample/spaces/applications/collections.json +1 -0
  290. dmart/sample/spaces/applications/configurations/.dm/meta.folder.json +1 -0
  291. dmart/sample/spaces/applications/configurations/time_out.json +1 -0
  292. dmart/sample/spaces/applications/configurations.json +19 -0
  293. dmart/sample/spaces/applications/errors.json +1 -0
  294. dmart/sample/spaces/applications/logs/.dm/meta.folder.json +1 -0
  295. dmart/sample/spaces/applications/logs.json +1 -0
  296. dmart/sample/spaces/applications/queries/.dm/meta.folder.json +1 -0
  297. dmart/sample/spaces/applications/queries/.dm/order/meta.content.json +1 -0
  298. dmart/sample/spaces/applications/queries/order.json +1 -0
  299. dmart/sample/spaces/applications/queries.json +1 -0
  300. dmart/sample/spaces/applications/schema/.dm/api/meta.schema.json +1 -0
  301. dmart/sample/spaces/applications/schema/.dm/configuration/meta.schema.json +1 -0
  302. dmart/sample/spaces/applications/schema/.dm/error/meta.schema.json +1 -0
  303. dmart/sample/spaces/applications/schema/.dm/log/meta.schema.json +1 -0
  304. dmart/sample/spaces/applications/schema/.dm/meta.folder.json +1 -0
  305. dmart/sample/spaces/applications/schema/.dm/query/meta.schema.json +16 -0
  306. dmart/sample/spaces/applications/schema/.dm/translation/meta.schema.json +1 -0
  307. dmart/sample/spaces/applications/schema/api.json +28 -0
  308. dmart/sample/spaces/applications/schema/configuration.json +1 -0
  309. dmart/sample/spaces/applications/schema/error.json +43 -0
  310. dmart/sample/spaces/applications/schema/log.json +1 -0
  311. dmart/sample/spaces/applications/schema/query.json +118 -0
  312. dmart/sample/spaces/applications/schema/translation.json +26 -0
  313. dmart/sample/spaces/applications/schema.json +1 -0
  314. dmart/sample/spaces/applications/translations/.dm/meta.folder.json +1 -0
  315. dmart/sample/spaces/applications/translations.json +1 -0
  316. dmart/sample/spaces/archive/.dm/meta.space.json +27 -0
  317. dmart/sample/spaces/custom_plugins/dummy/__pycache__/plugin.cpython-314.pyc +0 -0
  318. dmart/sample/spaces/custom_plugins/dummy/config.json +28 -0
  319. dmart/sample/spaces/custom_plugins/dummy/plugin.py +6 -0
  320. dmart/sample/spaces/custom_plugins/missed_entry/config.json +12 -0
  321. dmart/sample/spaces/custom_plugins/missed_entry/plugin.py +119 -0
  322. dmart/sample/spaces/custom_plugins/own_changed_notification/__pycache__/plugin.cpython-314.pyc +0 -0
  323. dmart/sample/spaces/custom_plugins/own_changed_notification/config.json +12 -0
  324. dmart/sample/spaces/custom_plugins/own_changed_notification/plugin.py +65 -0
  325. dmart/sample/spaces/custom_plugins/reports_stats/config.json +14 -0
  326. dmart/sample/spaces/custom_plugins/reports_stats/plugin.py +82 -0
  327. dmart/sample/spaces/custom_plugins/system_notification_sender/config.json +22 -0
  328. dmart/sample/spaces/custom_plugins/system_notification_sender/notification.py +268 -0
  329. dmart/sample/spaces/custom_plugins/system_notification_sender/plugin.py +98 -0
  330. dmart/sample/spaces/management/.dm/events.jsonl +32 -0
  331. dmart/sample/spaces/management/.dm/meta.space.json +48 -0
  332. dmart/sample/spaces/management/.dm/notifications/attachments.view.json/admin.json +36 -0
  333. dmart/sample/spaces/management/.dm/notifications/attachments.view.json/meta.admin.json +1 -0
  334. dmart/sample/spaces/management/.dm/notifications/attachments.view.json/meta.system.json +1 -0
  335. dmart/sample/spaces/management/.dm/notifications/attachments.view.json/system.json +32 -0
  336. dmart/sample/spaces/management/collections/.dm/meta.folder.json +1 -0
  337. dmart/sample/spaces/management/collections.json +1 -0
  338. dmart/sample/spaces/management/groups/.dm/meta.folder.json +1 -0
  339. dmart/sample/spaces/management/groups.json +1 -0
  340. dmart/sample/spaces/management/health_check/.dm/meta.folder.json +1 -0
  341. dmart/sample/spaces/management/health_check.json +1 -0
  342. dmart/sample/spaces/management/notifications/.dm/meta.folder.json +1 -0
  343. dmart/sample/spaces/management/notifications/admin/.dm/meta.folder.json +9 -0
  344. dmart/sample/spaces/management/notifications/system/.dm/meta.folder.json +9 -0
  345. dmart/sample/spaces/management/notifications.json +1 -0
  346. dmart/sample/spaces/management/permissions/.dm/access_applications/meta.permission.json +31 -0
  347. dmart/sample/spaces/management/permissions/.dm/access_applications_world/meta.permission.json +31 -0
  348. dmart/sample/spaces/management/permissions/.dm/access_messages/meta.permission.json +23 -0
  349. dmart/sample/spaces/management/permissions/.dm/access_personal/meta.permission.json +40 -0
  350. dmart/sample/spaces/management/permissions/.dm/access_protected/meta.permission.json +33 -0
  351. dmart/sample/spaces/management/permissions/.dm/access_public/meta.permission.json +24 -0
  352. dmart/sample/spaces/management/permissions/.dm/browse_all_folders/meta.permission.json +23 -0
  353. dmart/sample/spaces/management/permissions/.dm/create_log/meta.permission.json +24 -0
  354. dmart/sample/spaces/management/permissions/.dm/interviewer/meta.permission.json +1 -0
  355. dmart/sample/spaces/management/permissions/.dm/manage_applications/meta.permission.json +1 -0
  356. dmart/sample/spaces/management/permissions/.dm/manage_debug/meta.permission.json +25 -0
  357. dmart/sample/spaces/management/permissions/.dm/manage_spaces/meta.permission.json +24 -0
  358. dmart/sample/spaces/management/permissions/.dm/meta.folder.json +1 -0
  359. dmart/sample/spaces/management/permissions/.dm/rules_management_default/meta.permission.json +32 -0
  360. dmart/sample/spaces/management/permissions/.dm/super_manager/meta.permission.json +52 -0
  361. dmart/sample/spaces/management/permissions/.dm/view_activity_log/meta.permission.json +26 -0
  362. dmart/sample/spaces/management/permissions/.dm/view_collections/meta.permission.json +29 -0
  363. dmart/sample/spaces/management/permissions/.dm/view_logs/meta.permission.json +30 -0
  364. dmart/sample/spaces/management/permissions/.dm/view_roles/meta.permission.json +29 -0
  365. dmart/sample/spaces/management/permissions/.dm/view_users/meta.permission.json +25 -0
  366. dmart/sample/spaces/management/permissions/.dm/view_world/meta.permission.json +31 -0
  367. dmart/sample/spaces/management/permissions/.dm/world/meta.permission.json +35 -0
  368. dmart/sample/spaces/management/permissions.json +1 -0
  369. dmart/sample/spaces/management/requests.json +1 -0
  370. dmart/sample/spaces/management/roles/.dm/dummy/meta.role.json +12 -0
  371. dmart/sample/spaces/management/roles/.dm/logged_in/meta.role.json +18 -0
  372. dmart/sample/spaces/management/roles/.dm/manager/meta.role.json +13 -0
  373. dmart/sample/spaces/management/roles/.dm/meta.folder.json +1 -0
  374. dmart/sample/spaces/management/roles/.dm/moderator/meta.role.json +13 -0
  375. dmart/sample/spaces/management/roles/.dm/super_admin/meta.role.json +14 -0
  376. dmart/sample/spaces/management/roles/.dm/test_role/meta.role.json +13 -0
  377. dmart/sample/spaces/management/roles/.dm/world/meta.role.json +15 -0
  378. dmart/sample/spaces/management/roles.json +1 -0
  379. dmart/sample/spaces/management/schema/.dm/admin_notification_request/attachments.media/meta.ui_schema.json +10 -0
  380. dmart/sample/spaces/management/schema/.dm/admin_notification_request/attachments.media/ui_schema.json +32 -0
  381. dmart/sample/spaces/management/schema/.dm/admin_notification_request/meta.schema.json +1 -0
  382. dmart/sample/spaces/management/schema/.dm/api/meta.schema.json +1 -0
  383. dmart/sample/spaces/management/schema/.dm/folder_rendering/meta.schema.json +1 -0
  384. dmart/sample/spaces/management/schema/.dm/health_check/meta.schema.json +17 -0
  385. dmart/sample/spaces/management/schema/.dm/meta.folder.json +1 -0
  386. dmart/sample/spaces/management/schema/.dm/meta_schema/meta.schema.json +1 -0
  387. dmart/sample/spaces/management/schema/.dm/metafile/meta.schema.json +14 -0
  388. dmart/sample/spaces/management/schema/.dm/notification/meta.schema.json +1 -0
  389. dmart/sample/spaces/management/schema/.dm/system_notification_request/attachments.media/meta.ui_schema.json +10 -0
  390. dmart/sample/spaces/management/schema/.dm/system_notification_request/attachments.media/ui_schema.json +32 -0
  391. dmart/sample/spaces/management/schema/.dm/system_notification_request/meta.schema.json +1 -0
  392. dmart/sample/spaces/management/schema/.dm/view/meta.schema.json +1 -0
  393. dmart/sample/spaces/management/schema/.dm/workflow/meta.schema.json +1 -0
  394. dmart/sample/spaces/management/schema/admin_notification_request.json +89 -0
  395. dmart/sample/spaces/management/schema/api.json +1 -0
  396. dmart/sample/spaces/management/schema/folder_rendering.json +238 -0
  397. dmart/sample/spaces/management/schema/health_check.json +8 -0
  398. dmart/sample/spaces/management/schema/meta_schema.json +74 -0
  399. dmart/sample/spaces/management/schema/metafile.json +153 -0
  400. dmart/sample/spaces/management/schema/notification.json +28 -0
  401. dmart/sample/spaces/management/schema/system_notification_request.json +57 -0
  402. dmart/sample/spaces/management/schema/view.json +23 -0
  403. dmart/sample/spaces/management/schema/workflow.json +87 -0
  404. dmart/sample/spaces/management/schema.json +1 -0
  405. dmart/sample/spaces/management/users/.dm/alibaba/meta.user.json +23 -0
  406. dmart/sample/spaces/management/users/.dm/anonymous/meta.user.json +18 -0
  407. dmart/sample/spaces/management/users/.dm/dmart/meta.user.json +26 -0
  408. dmart/sample/spaces/management/users/.dm/meta.folder.json +14 -0
  409. dmart/sample/spaces/management/workflows/.dm/channel/meta.content.json +1 -0
  410. dmart/sample/spaces/management/workflows/.dm/meta.folder.json +1 -0
  411. dmart/sample/spaces/management/workflows/channel.json +148 -0
  412. dmart/sample/spaces/management/workflows.json +1 -0
  413. dmart/sample/spaces/maqola/.dm/meta.space.json +33 -0
  414. dmart/sample/spaces/personal/.dm/meta.space.json +24 -0
  415. dmart/sample/spaces/personal/people/.dm/meta.folder.json +1 -0
  416. dmart/sample/spaces/personal/people/dmart/.dm/meta.folder.json +1 -0
  417. dmart/sample/spaces/personal/people/dmart/messages/.dm/0b5f7e7f/meta.content.json +1 -0
  418. dmart/sample/spaces/personal/people/dmart/messages/.dm/meta.folder.json +1 -0
  419. dmart/sample/spaces/personal/people/dmart/messages/.dm/mytest/meta.content.json +1 -0
  420. dmart/sample/spaces/personal/people/dmart/messages/0b5f7e7f.json +1 -0
  421. dmart/sample/spaces/personal/people/dmart/messages/mytest.json +1 -0
  422. dmart/sample/spaces/personal/people/dmart/notifications/.dm/meta.folder.json +1 -0
  423. dmart/sample/spaces/personal/people/dmart/private/.dm/inner/meta.content.json +1 -0
  424. dmart/sample/spaces/personal/people/dmart/private/.dm/meta.folder.json +1 -0
  425. dmart/sample/spaces/personal/people/dmart/private/inner.json +1 -0
  426. dmart/sample/spaces/personal/people/dmart/protected/.dm/avatar/meta.content.json +1 -0
  427. dmart/sample/spaces/personal/people/dmart/protected/.dm/meta.folder.json +1 -0
  428. dmart/sample/spaces/personal/people/dmart/protected/avatar.png +0 -0
  429. dmart/sample/spaces/personal/people/dmart/public/.dm/meta.folder.json +1 -0
  430. dmart/sample/test/.gitignore +2 -0
  431. dmart/sample/test/createcontent.json +9 -0
  432. dmart/sample/test/createmedia.json +9 -0
  433. dmart/sample/test/createmedia_entry.json +6 -0
  434. dmart/sample/test/createschema.json +8 -0
  435. dmart/sample/test/createschemawork.json +11 -0
  436. dmart/sample/test/createticket.json +13 -0
  437. dmart/sample/test/data.json +4 -0
  438. dmart/sample/test/deletecontent.json +12 -0
  439. dmart/sample/test/logo.jpeg +0 -0
  440. dmart/sample/test/my.jpg +0 -0
  441. dmart/sample/test/myticket.json +23 -0
  442. dmart/sample/test/resources.csv +12 -0
  443. dmart/sample/test/schema.json +16 -0
  444. dmart/sample/test/temp.json +1 -0
  445. dmart/sample/test/test.dmart +45 -0
  446. dmart/sample/test/ticket_schema.json +23 -0
  447. dmart/sample/test/ticket_workflow.json +85 -0
  448. dmart/sample/test/ticketbody.json +4 -0
  449. dmart/sample/test/ticketcontent.json +14 -0
  450. dmart/sample/test/updatecontent.json +20 -0
  451. dmart/sample/test/workflow_schema.json +68 -0
  452. dmart/scheduled_notification_handler.py +121 -0
  453. dmart/schema_migration.py +208 -0
  454. dmart/schema_modulate.py +192 -0
  455. dmart/set_admin_passwd.py +75 -0
  456. dmart/sync.py +202 -0
  457. dmart/test_utils.py +34 -0
  458. dmart/utils/__init__.py +0 -0
  459. dmart/utils/access_control.py +306 -0
  460. dmart/utils/async_request.py +8 -0
  461. dmart/utils/exporter.py +309 -0
  462. dmart/utils/firebase_notifier.py +57 -0
  463. dmart/utils/generate_email.py +37 -0
  464. dmart/utils/helpers.py +352 -0
  465. dmart/utils/hypercorn_config.py +12 -0
  466. dmart/utils/internal_error_code.py +60 -0
  467. dmart/utils/jwt.py +124 -0
  468. dmart/utils/logger.py +167 -0
  469. dmart/utils/middleware.py +99 -0
  470. dmart/utils/notification.py +75 -0
  471. dmart/utils/password_hashing.py +16 -0
  472. dmart/utils/plugin_manager.py +202 -0
  473. dmart/utils/query_policies_helper.py +128 -0
  474. dmart/utils/regex.py +44 -0
  475. dmart/utils/repository.py +529 -0
  476. dmart/utils/router_helper.py +19 -0
  477. dmart/utils/settings.py +212 -0
  478. dmart/utils/sms_notifier.py +21 -0
  479. dmart/utils/social_sso.py +67 -0
  480. dmart/utils/templates/activation.html.j2 +26 -0
  481. dmart/utils/templates/reminder.html.j2 +17 -0
  482. dmart/utils/ticket_sys_utils.py +203 -0
  483. dmart/utils/web_notifier.py +29 -0
  484. dmart/websocket.py +231 -0
  485. dmart-1.4.40.post8.dist-info/METADATA +75 -0
  486. dmart-1.4.40.post8.dist-info/RECORD +489 -0
  487. dmart-1.4.40.post8.dist-info/WHEEL +5 -0
  488. dmart-1.4.40.post8.dist-info/entry_points.txt +2 -0
  489. dmart-1.4.40.post8.dist-info/top_level.txt +1 -0
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env -S BACKEND_ENV=config.env python3
2
+
3
+ import asyncio
4
+ from datetime import datetime
5
+ import json
6
+ from time import time
7
+ import os
8
+ import shutil
9
+ import sys
10
+ import argparse
11
+ from utils.helpers import camel_case
12
+ from data_adapters.file.redis_services import RedisServices
13
+ from utils.settings import settings
14
+ from typing import Awaitable
15
+
16
+
17
+ def redis_doc_to_meta(doc: dict):
18
+ meta_doc_content = {}
19
+ resource_class = getattr(
20
+ sys.modules["models.core"],
21
+ camel_case(doc["resource_type"]),
22
+ )
23
+ for key, value in doc.items():
24
+ if key in resource_class.model_fields.keys():
25
+ meta_doc_content[key] = value
26
+ meta_doc_content["created_at"] = datetime.fromtimestamp(
27
+ meta_doc_content["created_at"]
28
+ )
29
+ meta_doc_content["updated_at"] = datetime.fromtimestamp(
30
+ meta_doc_content["updated_at"]
31
+ )
32
+ return resource_class.model_validate(meta_doc_content)
33
+
34
+
35
+ async def archive(space: str, subpath: str, schema: str, olderthan: int):
36
+ """
37
+ Archives records from a specific space, subpath, and schema.
38
+
39
+ Args:
40
+ space (str): The name of the space.
41
+ subpath (str): The subpath within the space.
42
+ schema (str): The schema name.
43
+
44
+ Returns:
45
+ None
46
+ """
47
+ limit = 10000
48
+ counter = 0
49
+
50
+ timestamp = int(time()) - (olderthan * 24 * 60 * 60)
51
+ async with RedisServices() as redis_services:
52
+ while True:
53
+ redis_res = await redis_services.search(
54
+ space_name=space,
55
+ schema_name=schema,
56
+ search=f"(@updated_at:[-inf {timestamp}])",
57
+ filters={
58
+ "subpath": [subpath],
59
+ },
60
+ exact_subpath=True,
61
+ limit=limit,
62
+ offset=0,
63
+
64
+ )
65
+ if not redis_res or redis_res["total"] == 0:
66
+ print(f"No more data left. {redis_res=}")
67
+ break
68
+ counter += redis_res["total"]
69
+
70
+ search_res = redis_res["data"]
71
+
72
+ for redis_document in search_res:
73
+ record = json.loads(redis_document)
74
+
75
+ try:
76
+ # Move payload file
77
+ payload_file = f"{settings.spaces_folder}/{space}/{record['subpath']}/{record.get('shortname')}.json"
78
+ if os.path.exists(payload_file):
79
+ os.makedirs(f"{settings.spaces_folder}/archive/{space}/{record['subpath']}", exist_ok=True)
80
+ shutil.move(
81
+ src=payload_file,
82
+ dst=f"{settings.spaces_folder}/archive/{space}/{record['subpath']}/{record.get('shortname')}.json",
83
+ )
84
+
85
+ # Move meta folder / files
86
+ meta_folder = f"{settings.spaces_folder}/{space}/{record['subpath']}"
87
+ dest_folder = f"{settings.spaces_folder}/archive/{space}/{record['subpath']}"
88
+ if record["resource_type"] != "folder":
89
+ meta_folder += "/.dm"
90
+ dest_folder += "/.dm"
91
+
92
+
93
+ os.makedirs(
94
+ f"{dest_folder}", exist_ok=True
95
+ )
96
+ shutil.move(
97
+ src = f"{meta_folder}/{record.get('shortname')}",
98
+ dst=f"{dest_folder}",
99
+ )
100
+
101
+ # Delete Payload Doc from Redis
102
+ if record.get("payload_doc_id"):
103
+ x = redis_services.json().delete(key=record.get("payload_doc_id"))
104
+ if isinstance(x, Awaitable):
105
+ await x
106
+
107
+ # Delete Meta Doc from Redis
108
+ if "meta_doc_id" in record:
109
+ y = redis_services.json().delete(key=record.get("meta_doc_id"))
110
+ if isinstance(y, Awaitable):
111
+ await y
112
+ else:
113
+ await redis_services.delete_doc(
114
+ space,
115
+ "meta",
116
+ record.get("shortname"),
117
+ record["subpath"],
118
+ )
119
+ except Exception as e:
120
+ print(f"Error archiving {record.get('shortname')}: {e} at line {sys.exc_info()[-1]}")
121
+ continue
122
+ print(f'Processed {counter}')
123
+ await RedisServices().close_pool()
124
+
125
+ if __name__ == "__main__":
126
+ parser = argparse.ArgumentParser(
127
+ description="Script for archiving records from different spaces and subpaths."
128
+ )
129
+ parser.add_argument("space", type=str, help="The name of the space")
130
+ parser.add_argument("subpath", type=str, help="The subpath within the space")
131
+ parser.add_argument(
132
+ "schema",
133
+ type=str,
134
+ help="The subpath within the space. Optional, if not provided move everything",
135
+ nargs="?",
136
+ )
137
+ parser.add_argument(
138
+ "olderthan",
139
+ type=int,
140
+ help="The number of day, older than which, the entries will be archived (based on updated_at)",
141
+ )
142
+
143
+ args = parser.parse_args()
144
+ space = args.space
145
+ subpath = args.subpath
146
+ olderthan = args.olderthan
147
+ schema = args.schema or "meta"
148
+
149
+ asyncio.run(archive(space, subpath, schema, olderthan))
150
+ print("Done.")
@@ -0,0 +1,331 @@
1
+ #!/usr/bin/env -S BACKEND_ENV=config.env python3
2
+
3
+ import argparse
4
+ from copy import copy
5
+ import json
6
+ import re
7
+ import traceback
8
+
9
+ import models.api as api
10
+ from data_adapters.adapter import data_adapter as db
11
+ import models.core as core
12
+ import sys
13
+ from models.enums import ContentType, ResourceType
14
+ from utils.helpers import camel_case, divide_chunks
15
+ from jsonschema.exceptions import ValidationError as SchemaValidationError
16
+ from data_adapters.file.redis_services import RedisServices
17
+ from data_adapters.file.adapter_helpers import generate_payload_string
18
+ from utils.settings import settings
19
+ import utils.regex as regex
20
+ import asyncio
21
+ from utils.access_control import access_control
22
+ from multiprocessing import Pool
23
+
24
+
25
+ async def load_data_to_redis(
26
+ space_name,
27
+ subpath,
28
+ allowed_resource_types
29
+ ) -> dict:
30
+ """
31
+ Load meta files inside subpath then store them to redis as :space_name:meta prefixed doc,
32
+ and if the meta file has a separate payload file follwing a schema
33
+ we loads the payload content and store it to redis as :space_name:schema_name prefixed doc
34
+ """
35
+ # start_time: int = int(time())
36
+
37
+ #print(f"\n\nSTART EXAMINING SUBPATH: {subpath} {int(time()) - start_time} ")
38
+
39
+ locators_len, locators = db.locators_query(
40
+ api.Query(
41
+ space_name=space_name,
42
+ subpath=subpath,
43
+ type=api.QueryType.subpath,
44
+ limit=10000000,
45
+ filter_types=allowed_resource_types,
46
+ )
47
+ )
48
+
49
+ # Add Folder locator to the loaded locators
50
+ folder_meta = settings.spaces_folder / space_name / subpath / ".dm/meta.folder.json"
51
+ if ResourceType.folder in allowed_resource_types and folder_meta.is_file():
52
+ folder_parts = subpath.split("/")
53
+ folder_locator = core.Locator(
54
+ type=ResourceType.folder,
55
+ space_name=space_name,
56
+ subpath="/".join(folder_parts[:-1]) or "/",
57
+ shortname=folder_parts[-1]
58
+ )
59
+ locators.append(folder_locator)
60
+ locators_len += 1
61
+
62
+ # print(f"\nEnded loading {locators_len} files, starting parsing data in each file {int(time()) - start_time}")
63
+
64
+ if locators_len <= 5000:
65
+ redis_docs_chunks = [await generate_redis_docs(locators)]
66
+ else:
67
+ with Pool() as pool:
68
+ multiple_results = [
69
+ pool.apply_async(generate_redis_docs_process, (locators_chunk, ))
70
+ for locators_chunk in divide_chunks(locators, 5000)
71
+ ]
72
+ redis_docs_chunks = [process_res.get() for process_res in multiple_results]
73
+
74
+
75
+ saved_docs = []
76
+ #print(f"""
77
+ # Completed parsing {locators_len} files,
78
+ # generated {len(redis_docs_chunks)} chunks of docs to be stored in Redis,
79
+ # time: {int(time()) - start_time}
80
+ #""")
81
+
82
+ async with RedisServices() as redis_man:
83
+ for redis_docs_chunk in redis_docs_chunks:
84
+ saved_docs += await redis_man.save_bulk(redis_docs_chunk)
85
+
86
+
87
+ return {"subpath": subpath, "documents": len(saved_docs)}
88
+
89
+
90
+ def generate_redis_docs_process(locators: list):
91
+ return asyncio.run(generate_redis_docs(locators))
92
+
93
+ async def generate_redis_docs(locators: list) -> list:
94
+ redis_docs = []
95
+ async with RedisServices() as redis_man:
96
+ for one in locators:
97
+ try:
98
+ myclass = getattr(sys.modules["models.core"], camel_case(one.type))
99
+ # print(f"{one=}")
100
+
101
+ try:
102
+ meta = await db.load(
103
+ space_name=one.space_name,
104
+ subpath=one.subpath,
105
+ shortname=one.shortname,
106
+ class_type=myclass,
107
+ user_shortname="anonymous",
108
+ )
109
+ except Exception as e:
110
+ print(e)
111
+ continue
112
+ meta_doc_id, meta_data = redis_man.prepare_meta_doc(
113
+ one.space_name, one.subpath, meta
114
+ )
115
+ payload_data = {}
116
+ if (
117
+ meta.payload
118
+ and isinstance(meta.payload.body, str)
119
+ and meta.payload.content_type == ContentType.json
120
+ and meta.payload.schema_shortname
121
+ ):
122
+ try:
123
+ payload_path = db.payload_path(
124
+ one.space_name, one.subpath, myclass
125
+ ) / str(meta.payload.body)
126
+ payload_data = json.loads(payload_path.read_text())
127
+ await db.validate_payload_with_schema(
128
+ payload_data=payload_data,
129
+ space_name=one.space_name,
130
+ schema_shortname=meta.payload.schema_shortname,
131
+ )
132
+ doc_id, payload = redis_man.prepare_payload_doc(
133
+ space_name=one.space_name,
134
+ subpath=one.subpath,
135
+ resource_type=one.type,
136
+ payload=copy(payload_data),
137
+ meta=meta,
138
+ )
139
+ payload.update(meta_data)
140
+ redis_docs.append({"doc_id": doc_id, "payload": payload})
141
+ except SchemaValidationError as _:
142
+ print(
143
+ f"Error: @{one.space_name}/{one.subpath}/{meta.shortname} "
144
+ f"does not match the schema {meta.payload.schema_shortname}"
145
+ )
146
+ except Exception as ex:
147
+ print(f"Error: @{one.space_name}:{one.subpath} {meta.shortname=}, {ex}")
148
+
149
+ meta_data["payload_string"] = await generate_payload_string(
150
+ db,
151
+ space_name=one.space_name,
152
+ subpath=one.subpath,
153
+ shortname=one.shortname,
154
+ payload=payload_data,
155
+ ) if settings.store_payload_string else ""
156
+
157
+ redis_docs.append({"doc_id": meta_doc_id, "payload": meta_data})
158
+
159
+ except Exception:
160
+ print(f"path: {one.space_name}/{one.subpath}/{one.shortname} ({one.type})")
161
+ print("stacktrace:")
162
+ print(f" {traceback.format_exc()}")
163
+
164
+ return redis_docs
165
+
166
+
167
+
168
+ async def load_custom_indices_data(for_space: str | None = None):
169
+ for i, index in enumerate(RedisServices.CUSTOM_INDICES):
170
+ if for_space and index["space"] != for_space:
171
+ continue
172
+
173
+ if i < len(RedisServices.CUSTOM_CLASSES) and issubclass(RedisServices.CUSTOM_CLASSES[i], core.Meta):
174
+ res = await load_data_to_redis(
175
+ index["space"],
176
+ index["subpath"],
177
+ [ResourceType(RedisServices.CUSTOM_CLASSES[i].__name__.lower())],
178
+ )
179
+ print(
180
+ f"{res['documents']}\tCustom {index['space']}:meta:{index['subpath']}"
181
+ )
182
+
183
+
184
+ async def traverse_subpaths_entries(
185
+ path,
186
+ space_name,
187
+ loaded_data,
188
+ for_subpaths: list | None = None,
189
+ ):
190
+ # print(f"{subpath_index=} @{space_name} {path=}")
191
+ space_parts_count = len(settings.spaces_folder.parts)
192
+ subpath_index = space_parts_count + 1
193
+
194
+ for subpath in path.iterdir():
195
+ # print(f"{subpath=} 1")
196
+
197
+ # print(f"{subpath=} 2 {subpath.is_dir()} {re.match(regex.SUBPATH, subpath.name)}")
198
+
199
+ if subpath.is_dir() and re.match(regex.SUBPATH, subpath.name):
200
+ await traverse_subpaths_entries(
201
+ subpath,
202
+ space_name,
203
+ loaded_data,
204
+ for_subpaths,
205
+ )
206
+
207
+ # print(f"{subpath=} 3")
208
+ subpath_name = "/".join(subpath.parts[subpath_index:])
209
+ if for_subpaths:
210
+ subpath_enabled = any(
211
+ [subpath_name.startswith(subpath) for subpath in for_subpaths]
212
+ )
213
+ if not subpath_enabled:
214
+ continue
215
+
216
+ # print(f"{subpath=} 4")
217
+ loaded_data.append(
218
+ await load_data_to_redis(
219
+ space_name,
220
+ subpath_name,
221
+ [
222
+ ResourceType.content,
223
+ ResourceType.ticket,
224
+ ResourceType.schema,
225
+ ResourceType.notification,
226
+ ResourceType.post,
227
+ ResourceType.folder
228
+ ],
229
+ )
230
+ )
231
+ return loaded_data
232
+
233
+
234
+ async def load_all_spaces_data_to_redis(
235
+ for_space: str | None = None, for_subpaths: list | None = None
236
+ ):
237
+ """
238
+ Loop over spaces and subpaths inside it and load the data to redis of indexing_enabled for the space
239
+ """
240
+ loaded_data = {}
241
+ spaces = await db.get_spaces()
242
+ for space_name, space_json in spaces.items():
243
+ space_obj = core.Space.model_validate_json(space_json)
244
+ if (for_space and for_space != space_name) or not space_obj.indexing_enabled:
245
+ continue
246
+
247
+ path = settings.spaces_folder / space_name
248
+ if not path.is_dir():
249
+ continue
250
+
251
+ space_meta_file = path / ".dm/meta.space.json"
252
+ if not space_meta_file.is_file():
253
+ continue
254
+
255
+ print(f"Checking space name: {space_name}")
256
+ path = settings.spaces_folder / space_name
257
+
258
+ loaded_data[
259
+ f"{space_name}"
260
+ ] = await traverse_subpaths_entries(
261
+ path, space_name, [], for_subpaths
262
+ )
263
+
264
+ await load_custom_indices_data(for_space)
265
+
266
+ return loaded_data
267
+
268
+
269
+ async def main(
270
+ for_space: str | None = None,
271
+ for_schemas: list | None = None,
272
+ for_subpaths: list | None = None,
273
+ flushall: bool = False
274
+ ):
275
+
276
+ try:
277
+ async with RedisServices() as redis_man:
278
+ if flushall:
279
+ print("FLUSHALL")
280
+ await redis_man.flushall()
281
+
282
+ print("Intializing spaces")
283
+ await db.initialize_spaces()
284
+
285
+ print(f"Creating Redis indices: {for_space=} {for_schemas=}")
286
+ await access_control.load_permissions_and_roles()
287
+ await redis_man.create_indices(
288
+ for_space=for_space,
289
+ for_schemas=for_schemas,
290
+ del_docs=not bool(for_subpaths)
291
+ )
292
+ res = await load_all_spaces_data_to_redis(for_space, for_subpaths)
293
+ for space_name, loaded_data in res.items():
294
+ if loaded_data:
295
+ for item in loaded_data:
296
+ print(f"{item['documents']}\tRegular {space_name}/{item['subpath']}")
297
+ finally:
298
+ await RedisServices().close_pool()
299
+
300
+
301
+
302
+ if __name__ == "__main__":
303
+ parser = argparse.ArgumentParser(
304
+ description="Recreate Redis indices based on the available schema definitions",
305
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
306
+ )
307
+ parser.add_argument("-p", "--space", help="recreate indices for this space only")
308
+ parser.add_argument(
309
+ "-c", "--schemas", nargs="*", help="recreate indices for this schemas only"
310
+ )
311
+ parser.add_argument(
312
+ "-s", "--subpaths", nargs="*", help="upload documents for this subpaths only"
313
+ )
314
+ parser.add_argument(
315
+ "--flushall", action='store_true', help="FLUSHALL data on Redis"
316
+ )
317
+
318
+ args = parser.parse_args()
319
+
320
+ asyncio.run(main(args.space, args.schemas, args.subpaths, args.flushall))
321
+
322
+ # test_search = redis_services.search(
323
+ # space_name="products",
324
+ # schema_name="offer",
325
+ # search="@cbs_name:DB_ATLDaily_600MB",
326
+ # filters={"subpath": ["offers"], "shortname": ["2140692"]},
327
+ # limit=10,
328
+ # offset=0,
329
+ # sort_by="cbs_id"
330
+ # )
331
+ # print("\n\n\nresult count: ", len(test_search), "\n\nresult: ", test_search)
@@ -0,0 +1,52 @@
1
+ import asyncio
2
+ import os
3
+ from models.core import Folder
4
+ from utils.settings import settings
5
+ from data_adapters.adapter import data_adapter as db
6
+
7
+
8
+ async def main() -> None:
9
+ users_processed = 0
10
+ folder_processed = 0
11
+
12
+ users_subpath = settings.spaces_folder / settings.management_space / "users/.dm"
13
+ users_iterator = os.scandir(users_subpath)
14
+ for entry in users_iterator:
15
+ if not entry.is_dir():
16
+ continue
17
+
18
+
19
+ folders = [
20
+ ("personal", "people", entry.name),
21
+ ("personal", f"people/{entry.name}", "notifications"),
22
+ ("personal", f"people/{entry.name}", "private"),
23
+ ("personal", f"people/{entry.name}", "protected"),
24
+ ("personal", f"people/{entry.name}", "public"),
25
+ ("personal", f"people/{entry.name}", "inbox"),
26
+ ]
27
+ for folder in folders:
28
+ if (settings.spaces_folder / folder[0] / folder[1] / folder[2]).is_dir():
29
+ continue
30
+ await db.internal_save_model(
31
+ space_name=folder[0],
32
+ subpath=folder[1],
33
+ meta=Folder(
34
+ shortname=folder[2],
35
+ is_active=True,
36
+ owner_shortname=entry.name
37
+ )
38
+ )
39
+ print(f"Created folder {folder} for user {entry.name}")
40
+ folder_processed += 1
41
+
42
+ users_processed += 1
43
+
44
+ users_iterator.close()
45
+
46
+ print(f"\n===== DONE ====== \nScanned {users_processed} users,\
47
+ Created {folder_processed} missing folders")
48
+
49
+
50
+ if __name__ == "__main__":
51
+
52
+ asyncio.run(main())
@@ -0,0 +1,68 @@
1
+ import json
2
+ from typing import Any
3
+ import aiofiles
4
+ from utils.helpers import csv_file_to_json
5
+ from utils.settings import settings
6
+ from pathlib import Path as FSPath
7
+ from jsonschema import Draft7Validator
8
+
9
+
10
+ def get_schema_path(space_name: str, schema_shortname: str):
11
+ # Tries to get the schema from the management space first
12
+ schema_path = (
13
+ settings.spaces_folder /
14
+ settings.management_space /
15
+ "schema" /
16
+ schema_shortname
17
+ )
18
+
19
+ if schema_path.is_file():
20
+ return schema_path
21
+
22
+ schema_path = (
23
+ settings.spaces_folder /
24
+ space_name /
25
+ "schema" /
26
+ schema_shortname
27
+ )
28
+
29
+ if not schema_path.is_file():
30
+ raise Exception(f"Invalid schema path, {schema_path=} is not a file")
31
+
32
+ return schema_path
33
+
34
+ async def validate_jsonl_with_schema(
35
+ file_path: FSPath,
36
+ space_name: str,
37
+ schema_shortname: str,
38
+ ) -> None:
39
+
40
+ schema_path = get_schema_path(
41
+ space_name=space_name,
42
+ schema_shortname=f"{schema_shortname}.json",
43
+ )
44
+
45
+ schema = json.loads(FSPath(schema_path).read_text())
46
+
47
+ async with aiofiles.open(file_path, "r") as file:
48
+ lines = await file.readlines()
49
+ for line in lines:
50
+ Draft7Validator(schema).validate(line)
51
+
52
+
53
+ async def validate_csv_with_schema(
54
+ file_path: FSPath,
55
+ space_name: str,
56
+ schema_shortname: str,
57
+ ) -> None:
58
+
59
+ schema_path = get_schema_path(
60
+ space_name=space_name,
61
+ schema_shortname=f"{schema_shortname}.json",
62
+ )
63
+
64
+ schema = json.loads(FSPath(schema_path).read_text())
65
+
66
+ jsonl: list[dict[str, Any]] = await csv_file_to_json(file_path)
67
+ for json_item in jsonl:
68
+ Draft7Validator(schema).validate(json_item)
@@ -0,0 +1,40 @@
1
+ import asyncio
2
+ import argparse
3
+ from typing import Awaitable
4
+ from data_adapters.file.redis_services import RedisServices
5
+
6
+ #!/usr/bin/env python
7
+
8
+ # Your code goes here
9
+
10
+ async def drop_index(space: str, schema: str) -> None:
11
+ try:
12
+ async with RedisServices() as redis_services:
13
+ print("Dropping Meta Docs")
14
+ # Delete Meta docs
15
+ document_ids = await redis_services.get_all_document_ids(f"{space}:meta", f"@schema_shortname:{schema}")
16
+ for id in document_ids:
17
+ x = redis_services.json().delete(id)
18
+ if x and isinstance(x, Awaitable):
19
+ await x
20
+ print(f"Deleted: {id}")
21
+
22
+ # Drop the index and delete it's docs
23
+ print("Dropping The Index")
24
+ await redis_services.drop_index(f"{space}:{schema}", True)
25
+ print("DONE.")
26
+ except Exception as e:
27
+ print(f"Error: {e}")
28
+
29
+
30
+ if __name__ == "__main__":
31
+ parser = argparse.ArgumentParser(description="Script to drop index and delete associated documents in Redis.")
32
+ parser.add_argument("space", help="Space name where the index is located.")
33
+ parser.add_argument("schema", help="Schema name to drop index for.")
34
+
35
+ args = parser.parse_args()
36
+
37
+ if args.schema == "meta":
38
+ print("Cannot drop index for schema 'meta'")
39
+
40
+ asyncio.run(drop_index(args.space, args.schema))