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.
- dmart/__init__.py +7 -0
- dmart/alembic/README +1 -0
- dmart/alembic/__init__.py +0 -0
- dmart/alembic/env.py +91 -0
- dmart/alembic/notes.txt +11 -0
- dmart/alembic/script.py.mako +28 -0
- dmart/alembic/scripts/__init__.py +0 -0
- dmart/alembic/scripts/calculate_checksums.py +77 -0
- dmart/alembic/scripts/migration_f7a4949eed19.py +28 -0
- dmart/alembic/versions/0f3d2b1a7c21_add_authz_materialized_views.py +87 -0
- dmart/alembic/versions/10d2041b94d4_last_checksum_history.py +62 -0
- dmart/alembic/versions/1cf4e1ee3cb8_ext_permission_with_filter_fields_values.py +33 -0
- dmart/alembic/versions/26bfe19b49d4_rm_failedloginattempts.py +42 -0
- dmart/alembic/versions/3c8bca2219cc_add_otp_table.py +38 -0
- dmart/alembic/versions/6675fd9dfe42_remove_unique_from_sessions_table.py +36 -0
- dmart/alembic/versions/71bc1df82e6a_adding_user_last_login_at.py +43 -0
- dmart/alembic/versions/74288ccbd3b5_initial.py +264 -0
- dmart/alembic/versions/7520a89a8467_rm_activesession_table.py +39 -0
- dmart/alembic/versions/848b623755a4_make_created_nd_updated_at_required.py +138 -0
- dmart/alembic/versions/8640dcbebf85_add_notes_to_users.py +32 -0
- dmart/alembic/versions/91c94250232a_adding_fk_on_owner_shortname.py +104 -0
- dmart/alembic/versions/98ecd6f56f9a_ext_meta_with_owner_group_shortname.py +66 -0
- dmart/alembic/versions/9aae9138c4ef_indexing_created_at_updated_at.py +80 -0
- dmart/alembic/versions/__init__.py +0 -0
- dmart/alembic/versions/b53f916b3f6d_json_to_jsonb.py +492 -0
- dmart/alembic/versions/eb5f1ec65156_adding_user_locked_to_device.py +36 -0
- dmart/alembic/versions/f7a4949eed19_adding_query_policies_to_meta.py +60 -0
- dmart/alembic.ini +117 -0
- dmart/api/__init__.py +0 -0
- dmart/api/info/__init__.py +0 -0
- dmart/api/info/router.py +109 -0
- dmart/api/managed/__init__.py +0 -0
- dmart/api/managed/router.py +1541 -0
- dmart/api/managed/utils.py +1879 -0
- dmart/api/public/__init__.py +0 -0
- dmart/api/public/router.py +758 -0
- dmart/api/qr/__init__.py +0 -0
- dmart/api/qr/router.py +108 -0
- dmart/api/user/__init__.py +0 -0
- dmart/api/user/model/__init__.py +0 -0
- dmart/api/user/model/errors.py +14 -0
- dmart/api/user/model/requests.py +165 -0
- dmart/api/user/model/responses.py +11 -0
- dmart/api/user/router.py +1413 -0
- dmart/api/user/service.py +270 -0
- dmart/bundler.py +52 -0
- dmart/cli.py +1133 -0
- dmart/config/__init__.py +0 -0
- dmart/config/channels.json +11 -0
- dmart/config/notification.json +17 -0
- dmart/config.env.sample +27 -0
- dmart/config.ini.sample +7 -0
- dmart/conftest.py +13 -0
- dmart/curl.sh +196 -0
- dmart/cxb/__init__.py +0 -0
- dmart/cxb/assets/@codemirror-Rn7_6DkE.js +10 -0
- dmart/cxb/assets/@edraj-CS4NwVbD.js +1 -0
- dmart/cxb/assets/@floating-ui-BwwcF-xh.js +1 -0
- dmart/cxb/assets/@formatjs-yKEsAtjs.js +1 -0
- dmart/cxb/assets/@fortawesome-DRW1UCdr.js +9 -0
- dmart/cxb/assets/@jsonquerylang-laKNoFFq.js +12 -0
- dmart/cxb/assets/@lezer-za4Q-8Ew.js +1 -0
- dmart/cxb/assets/@marijn-DXwl3gUT.js +1 -0
- dmart/cxb/assets/@popperjs-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/@replit--ERk53eB.js +1 -0
- dmart/cxb/assets/@roxi-CGMFK4i8.js +6 -0
- dmart/cxb/assets/@typewriter-cCzskkIv.js +17 -0
- dmart/cxb/assets/@zerodevx-BlBZjKxu.js +1 -0
- dmart/cxb/assets/@zerodevx-CVEpe6WZ.css +1 -0
- dmart/cxb/assets/BreadCrumbLite-DAhOx38v.js +1 -0
- dmart/cxb/assets/EntryRenderer-CCqV8Rkg.js +32 -0
- dmart/cxb/assets/EntryRenderer-DXytdFp9.css +1 -0
- dmart/cxb/assets/ListView-BQelo7vZ.js +16 -0
- dmart/cxb/assets/ListView-U8of-_c-.css +1 -0
- dmart/cxb/assets/Prism--hMplq-p.js +3 -0
- dmart/cxb/assets/Prism-Uh6uStUw.css +1 -0
- dmart/cxb/assets/Table2Cols-BsbwicQm.js +1 -0
- dmart/cxb/assets/_..-BvT6vdHa.css +1 -0
- dmart/cxb/assets/_...404_-fuLH_rX9.js +2 -0
- dmart/cxb/assets/_...fallback_-Ba_NLmAE.js +1 -0
- dmart/cxb/assets/_module-3HrtKAWo.js +3 -0
- dmart/cxb/assets/_module-DFKFq0AM.js +4 -0
- dmart/cxb/assets/_module-Dgq0ZVtz.js +1 -0
- dmart/cxb/assets/ajv-Cpj98o6Y.js +1 -0
- dmart/cxb/assets/axios-CG2WSiiR.js +6 -0
- dmart/cxb/assets/clsx-B-dksMZM.js +1 -0
- dmart/cxb/assets/codemirror-wrapped-line-indent-DPhKvljI.js +1 -0
- dmart/cxb/assets/compare-C3AjiGFR.js +1 -0
- dmart/cxb/assets/compute-scroll-into-view-Bl8rNFhg.js +1 -0
- dmart/cxb/assets/consolite-DlCuI0F9.js +1 -0
- dmart/cxb/assets/crelt-C8TCjufn.js +1 -0
- dmart/cxb/assets/date-fns-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/deepmerge-rn4rBaHU.js +1 -0
- dmart/cxb/assets/dmart_services-AL6-IdDE.js +1 -0
- dmart/cxb/assets/downloadFile-D08i0YDh.js +1 -0
- dmart/cxb/assets/easy-signal-BiPFIK3O.js +1 -0
- dmart/cxb/assets/esm-env-rsSWfq8L.js +1 -0
- dmart/cxb/assets/export-OF_rTiXu.js +1 -0
- dmart/cxb/assets/fast-deep-equal-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/fast-diff-C-IidNf4.js +1 -0
- dmart/cxb/assets/fast-uri-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/flowbite-svelte-BLvjb-sa.js +1 -0
- dmart/cxb/assets/flowbite-svelte-CD54FDqW.css +1 -0
- dmart/cxb/assets/flowbite-svelte-icons-BI8GVhw_.js +1 -0
- dmart/cxb/assets/github-slugger-CQ4oX9Ud.js +1 -0
- dmart/cxb/assets/global-igKv-1g9.js +1 -0
- dmart/cxb/assets/hookar-BMRD9G9H.js +1 -0
- dmart/cxb/assets/immutable-json-patch-DtRO2E_S.js +1 -0
- dmart/cxb/assets/import-1vE3gBat.js +1 -0
- dmart/cxb/assets/index-B-eTh-ZX.js +1 -0
- dmart/cxb/assets/index-BSsK-X71.js +1 -0
- dmart/cxb/assets/index-BVyxzKtH.js +1 -0
- dmart/cxb/assets/index-BdeNM69f.js +1 -0
- dmart/cxb/assets/index-CC-A1ipE.js +1 -0
- dmart/cxb/assets/index-CQohGiYB.js +1 -0
- dmart/cxb/assets/index-ChjnkpdZ.js +4 -0
- dmart/cxb/assets/index-DLP7csA4.js +1 -0
- dmart/cxb/assets/index-DTfhnhwd.js +1 -0
- dmart/cxb/assets/index-DdXRK7n9.js +2 -0
- dmart/cxb/assets/index-DtiCmB4o.js +1 -0
- dmart/cxb/assets/index-NBrXBlLA.css +2 -0
- dmart/cxb/assets/index-X1uNehO7.js +1 -0
- dmart/cxb/assets/index-nrQW6Nrr.js +1 -0
- dmart/cxb/assets/info-B986lRiM.js +1 -0
- dmart/cxb/assets/intl-messageformat-Dc5UU-HB.js +3 -0
- dmart/cxb/assets/jmespath-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/json-schema-traverse-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/json-source-map-DRgZidqy.js +5 -0
- dmart/cxb/assets/jsonpath-plus-l0sNRNKZ.js +1 -0
- dmart/cxb/assets/jsonrepair-B30Dx381.js +8 -0
- dmart/cxb/assets/lodash-es-DZVAA2ox.js +1 -0
- dmart/cxb/assets/marked-DKjyhwJX.js +56 -0
- dmart/cxb/assets/marked-gfm-heading-id-U5zO829x.js +2 -0
- dmart/cxb/assets/marked-mangle-CDMeiHC6.js +1 -0
- dmart/cxb/assets/memoize-one-BdPwpGay.js +1 -0
- dmart/cxb/assets/natural-compare-lite-Bg2Xcf-o.js +7 -0
- dmart/cxb/assets/pagination-svelte-D5CyoiE_.js +13 -0
- dmart/cxb/assets/pagination-svelte-v10nAbbM.css +1 -0
- dmart/cxb/assets/plantuml-encoder-C47mzt9T.js +1 -0
- dmart/cxb/assets/prismjs-DTUiLGJu.js +9 -0
- dmart/cxb/assets/profile-BUf-tKMe.js +1 -0
- dmart/cxb/assets/query-CNmXTsgf.js +1 -0
- dmart/cxb/assets/queryHelpers-C9iBWwqe.js +1 -0
- dmart/cxb/assets/scroll-into-view-if-needed-KR58zyjF.js +1 -0
- dmart/cxb/assets/spaces-0oyGvpii.js +1 -0
- dmart/cxb/assets/style-mod-Bs6eFhZE.js +3 -0
- dmart/cxb/assets/svelte-B2XmcTi_.js +4 -0
- dmart/cxb/assets/svelte-awesome-COLlx0DN.css +1 -0
- dmart/cxb/assets/svelte-awesome-DhnMA6Q_.js +1 -0
- dmart/cxb/assets/svelte-datatables-net-CY7LBj6I.js +1 -0
- dmart/cxb/assets/svelte-floating-ui-BlS3sOAQ.js +1 -0
- dmart/cxb/assets/svelte-i18n-CT2KkQaN.js +3 -0
- dmart/cxb/assets/svelte-jsoneditor-BzfX6Usi.css +1 -0
- dmart/cxb/assets/svelte-jsoneditor-CUGSvWId.js +25 -0
- dmart/cxb/assets/svelte-select-CegQKzqH.css +1 -0
- dmart/cxb/assets/svelte-select-CjHAt_85.js +6 -0
- dmart/cxb/assets/tailwind-merge-CJvxXMcu.js +1 -0
- dmart/cxb/assets/tailwind-variants-Cj20BoQ3.js +1 -0
- dmart/cxb/assets/toast-B9WDyfyI.js +1 -0
- dmart/cxb/assets/tslib-pJfR_DrR.js +1 -0
- dmart/cxb/assets/typewriter-editor-DkTVIJdm.js +25 -0
- dmart/cxb/assets/user-DeK_NB5v.js +1 -0
- dmart/cxb/assets/vanilla-picker-l5rcX3cq.js +8 -0
- dmart/cxb/assets/w3c-keyname-Vcq4gwWv.js +1 -0
- dmart/cxb/config.json +11 -0
- dmart/cxb/config.sample.json +11 -0
- dmart/cxb/favicon.ico +0 -0
- dmart/cxb/favicon.png +0 -0
- dmart/cxb/index.html +28 -0
- dmart/data_adapters/__init__.py +0 -0
- dmart/data_adapters/adapter.py +16 -0
- dmart/data_adapters/base_data_adapter.py +467 -0
- dmart/data_adapters/file/__init__.py +0 -0
- dmart/data_adapters/file/adapter.py +2043 -0
- dmart/data_adapters/file/adapter_helpers.py +1013 -0
- dmart/data_adapters/file/archive.py +150 -0
- dmart/data_adapters/file/create_index.py +331 -0
- dmart/data_adapters/file/create_users_folders.py +52 -0
- dmart/data_adapters/file/custom_validations.py +68 -0
- dmart/data_adapters/file/drop_index.py +40 -0
- dmart/data_adapters/file/health_check.py +560 -0
- dmart/data_adapters/file/redis_services.py +1110 -0
- dmart/data_adapters/helpers.py +27 -0
- dmart/data_adapters/sql/__init__.py +0 -0
- dmart/data_adapters/sql/adapter.py +3218 -0
- dmart/data_adapters/sql/adapter_helpers.py +491 -0
- dmart/data_adapters/sql/create_tables.py +451 -0
- dmart/data_adapters/sql/create_users_folders.py +53 -0
- dmart/data_adapters/sql/db_to_json_migration.py +485 -0
- dmart/data_adapters/sql/health_check_sql.py +232 -0
- dmart/data_adapters/sql/json_to_db_migration.py +454 -0
- dmart/data_adapters/sql/update_query_policies.py +101 -0
- dmart/data_generator.py +81 -0
- dmart/dmart.py +761 -0
- dmart/get_settings.py +7 -0
- dmart/hypercorn_config.toml +3 -0
- dmart/info.json +1 -0
- dmart/languages/__init__.py +0 -0
- dmart/languages/arabic.json +15 -0
- dmart/languages/english.json +16 -0
- dmart/languages/kurdish.json +14 -0
- dmart/languages/loader.py +12 -0
- dmart/login_creds.sh +7 -0
- dmart/login_creds.sh.sample +7 -0
- dmart/main.py +563 -0
- dmart/manifest.sh +12 -0
- dmart/migrate.py +24 -0
- dmart/models/__init__.py +0 -0
- dmart/models/api.py +203 -0
- dmart/models/core.py +597 -0
- dmart/models/enums.py +255 -0
- dmart/password_gen.py +8 -0
- dmart/plugins/__init__.py +0 -0
- dmart/plugins/action_log/__init__.py +0 -0
- dmart/plugins/action_log/config.json +13 -0
- dmart/plugins/action_log/plugin.py +121 -0
- dmart/plugins/admin_notification_sender/__init__.py +0 -0
- dmart/plugins/admin_notification_sender/config.json +13 -0
- dmart/plugins/admin_notification_sender/plugin.py +124 -0
- dmart/plugins/ldap_manager/__init__.py +0 -0
- dmart/plugins/ldap_manager/config.json +12 -0
- dmart/plugins/ldap_manager/dmart.schema +146 -0
- dmart/plugins/ldap_manager/plugin.py +100 -0
- dmart/plugins/ldap_manager/slapd.conf +53 -0
- dmart/plugins/local_notification/__init__.py +0 -0
- dmart/plugins/local_notification/config.json +13 -0
- dmart/plugins/local_notification/plugin.py +123 -0
- dmart/plugins/realtime_updates_notifier/__init__.py +0 -0
- dmart/plugins/realtime_updates_notifier/config.json +12 -0
- dmart/plugins/realtime_updates_notifier/plugin.py +58 -0
- dmart/plugins/redis_db_update/__init__.py +0 -0
- dmart/plugins/redis_db_update/config.json +13 -0
- dmart/plugins/redis_db_update/plugin.py +188 -0
- dmart/plugins/resource_folders_creation/__init__.py +0 -0
- dmart/plugins/resource_folders_creation/config.json +12 -0
- dmart/plugins/resource_folders_creation/plugin.py +81 -0
- dmart/plugins/system_notification_sender/__init__.py +0 -0
- dmart/plugins/system_notification_sender/config.json +13 -0
- dmart/plugins/system_notification_sender/plugin.py +188 -0
- dmart/plugins/update_access_controls/__init__.py +0 -0
- dmart/plugins/update_access_controls/config.json +12 -0
- dmart/plugins/update_access_controls/plugin.py +9 -0
- dmart/publish.sh +57 -0
- dmart/pylint.sh +16 -0
- dmart/pyrightconfig.json +7 -0
- dmart/redis_connections.sh +13 -0
- dmart/reload.sh +56 -0
- dmart/run.sh +3 -0
- dmart/run_notification_campaign.py +85 -0
- dmart/sample/spaces/applications/.dm/meta.space.json +30 -0
- dmart/sample/spaces/applications/api/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/api/.dm/query_all_applications/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/.dm/test_by_saad/attachments.media/meta.warframe.json +1 -0
- dmart/sample/spaces/applications/api/.dm/test_by_saad/attachments.media/warframe.png +0 -0
- dmart/sample/spaces/applications/api/.dm/test_by_saad/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/.dm/user_profile/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/create_log/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/create_public_logs/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/query_all_translated_data/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/query_logs/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/query_translated_enums/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/query_translated_others/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/.dm/query_translated_resolution/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/applications/create_log.json +1 -0
- dmart/sample/spaces/applications/api/applications/create_public_logs.json +1 -0
- dmart/sample/spaces/applications/api/applications/query_all_translated_data.json +1 -0
- dmart/sample/spaces/applications/api/applications/query_logs.json +1 -0
- dmart/sample/spaces/applications/api/applications/query_translated_enums.json +1 -0
- dmart/sample/spaces/applications/api/applications/query_translated_others.json +1 -0
- dmart/sample/spaces/applications/api/applications/query_translated_resolution.json +1 -0
- dmart/sample/spaces/applications/api/applications.json +1 -0
- dmart/sample/spaces/applications/api/management/.dm/create_subaccount/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/management/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/api/management/.dm/update_password/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/management/create_subaccount.json +53 -0
- dmart/sample/spaces/applications/api/management/update_password.json +1 -0
- dmart/sample/spaces/applications/api/management.json +1 -0
- dmart/sample/spaces/applications/api/query_all_applications.json +15 -0
- dmart/sample/spaces/applications/api/test_by_saad.json +1 -0
- dmart/sample/spaces/applications/api/user/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/api/user/.dm/test_by_saad/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/user/.dm/user_profile/meta.content.json +1 -0
- dmart/sample/spaces/applications/api/user/test_by_saad.json +1 -0
- dmart/sample/spaces/applications/api/user/user_profile.json +1 -0
- dmart/sample/spaces/applications/api/user_profile.json +1 -0
- dmart/sample/spaces/applications/api.json +1 -0
- dmart/sample/spaces/applications/collections/.dm/meta.folder.json +19 -0
- dmart/sample/spaces/applications/collections.json +1 -0
- dmart/sample/spaces/applications/configurations/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/configurations/time_out.json +1 -0
- dmart/sample/spaces/applications/configurations.json +19 -0
- dmart/sample/spaces/applications/errors.json +1 -0
- dmart/sample/spaces/applications/logs/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/logs.json +1 -0
- dmart/sample/spaces/applications/queries/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/queries/.dm/order/meta.content.json +1 -0
- dmart/sample/spaces/applications/queries/order.json +1 -0
- dmart/sample/spaces/applications/queries.json +1 -0
- dmart/sample/spaces/applications/schema/.dm/api/meta.schema.json +1 -0
- dmart/sample/spaces/applications/schema/.dm/configuration/meta.schema.json +1 -0
- dmart/sample/spaces/applications/schema/.dm/error/meta.schema.json +1 -0
- dmart/sample/spaces/applications/schema/.dm/log/meta.schema.json +1 -0
- dmart/sample/spaces/applications/schema/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/schema/.dm/query/meta.schema.json +16 -0
- dmart/sample/spaces/applications/schema/.dm/translation/meta.schema.json +1 -0
- dmart/sample/spaces/applications/schema/api.json +28 -0
- dmart/sample/spaces/applications/schema/configuration.json +1 -0
- dmart/sample/spaces/applications/schema/error.json +43 -0
- dmart/sample/spaces/applications/schema/log.json +1 -0
- dmart/sample/spaces/applications/schema/query.json +118 -0
- dmart/sample/spaces/applications/schema/translation.json +26 -0
- dmart/sample/spaces/applications/schema.json +1 -0
- dmart/sample/spaces/applications/translations/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/applications/translations.json +1 -0
- dmart/sample/spaces/archive/.dm/meta.space.json +27 -0
- dmart/sample/spaces/custom_plugins/dummy/__pycache__/plugin.cpython-314.pyc +0 -0
- dmart/sample/spaces/custom_plugins/dummy/config.json +28 -0
- dmart/sample/spaces/custom_plugins/dummy/plugin.py +6 -0
- dmart/sample/spaces/custom_plugins/missed_entry/config.json +12 -0
- dmart/sample/spaces/custom_plugins/missed_entry/plugin.py +119 -0
- dmart/sample/spaces/custom_plugins/own_changed_notification/__pycache__/plugin.cpython-314.pyc +0 -0
- dmart/sample/spaces/custom_plugins/own_changed_notification/config.json +12 -0
- dmart/sample/spaces/custom_plugins/own_changed_notification/plugin.py +65 -0
- dmart/sample/spaces/custom_plugins/reports_stats/config.json +14 -0
- dmart/sample/spaces/custom_plugins/reports_stats/plugin.py +82 -0
- dmart/sample/spaces/custom_plugins/system_notification_sender/config.json +22 -0
- dmart/sample/spaces/custom_plugins/system_notification_sender/notification.py +268 -0
- dmart/sample/spaces/custom_plugins/system_notification_sender/plugin.py +98 -0
- dmart/sample/spaces/management/.dm/events.jsonl +32 -0
- dmart/sample/spaces/management/.dm/meta.space.json +48 -0
- dmart/sample/spaces/management/.dm/notifications/attachments.view.json/admin.json +36 -0
- dmart/sample/spaces/management/.dm/notifications/attachments.view.json/meta.admin.json +1 -0
- dmart/sample/spaces/management/.dm/notifications/attachments.view.json/meta.system.json +1 -0
- dmart/sample/spaces/management/.dm/notifications/attachments.view.json/system.json +32 -0
- dmart/sample/spaces/management/collections/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/collections.json +1 -0
- dmart/sample/spaces/management/groups/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/groups.json +1 -0
- dmart/sample/spaces/management/health_check/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/health_check.json +1 -0
- dmart/sample/spaces/management/notifications/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/notifications/admin/.dm/meta.folder.json +9 -0
- dmart/sample/spaces/management/notifications/system/.dm/meta.folder.json +9 -0
- dmart/sample/spaces/management/notifications.json +1 -0
- dmart/sample/spaces/management/permissions/.dm/access_applications/meta.permission.json +31 -0
- dmart/sample/spaces/management/permissions/.dm/access_applications_world/meta.permission.json +31 -0
- dmart/sample/spaces/management/permissions/.dm/access_messages/meta.permission.json +23 -0
- dmart/sample/spaces/management/permissions/.dm/access_personal/meta.permission.json +40 -0
- dmart/sample/spaces/management/permissions/.dm/access_protected/meta.permission.json +33 -0
- dmart/sample/spaces/management/permissions/.dm/access_public/meta.permission.json +24 -0
- dmart/sample/spaces/management/permissions/.dm/browse_all_folders/meta.permission.json +23 -0
- dmart/sample/spaces/management/permissions/.dm/create_log/meta.permission.json +24 -0
- dmart/sample/spaces/management/permissions/.dm/interviewer/meta.permission.json +1 -0
- dmart/sample/spaces/management/permissions/.dm/manage_applications/meta.permission.json +1 -0
- dmart/sample/spaces/management/permissions/.dm/manage_debug/meta.permission.json +25 -0
- dmart/sample/spaces/management/permissions/.dm/manage_spaces/meta.permission.json +24 -0
- dmart/sample/spaces/management/permissions/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/permissions/.dm/rules_management_default/meta.permission.json +32 -0
- dmart/sample/spaces/management/permissions/.dm/super_manager/meta.permission.json +52 -0
- dmart/sample/spaces/management/permissions/.dm/view_activity_log/meta.permission.json +26 -0
- dmart/sample/spaces/management/permissions/.dm/view_collections/meta.permission.json +29 -0
- dmart/sample/spaces/management/permissions/.dm/view_logs/meta.permission.json +30 -0
- dmart/sample/spaces/management/permissions/.dm/view_roles/meta.permission.json +29 -0
- dmart/sample/spaces/management/permissions/.dm/view_users/meta.permission.json +25 -0
- dmart/sample/spaces/management/permissions/.dm/view_world/meta.permission.json +31 -0
- dmart/sample/spaces/management/permissions/.dm/world/meta.permission.json +35 -0
- dmart/sample/spaces/management/permissions.json +1 -0
- dmart/sample/spaces/management/requests.json +1 -0
- dmart/sample/spaces/management/roles/.dm/dummy/meta.role.json +12 -0
- dmart/sample/spaces/management/roles/.dm/logged_in/meta.role.json +18 -0
- dmart/sample/spaces/management/roles/.dm/manager/meta.role.json +13 -0
- dmart/sample/spaces/management/roles/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/roles/.dm/moderator/meta.role.json +13 -0
- dmart/sample/spaces/management/roles/.dm/super_admin/meta.role.json +14 -0
- dmart/sample/spaces/management/roles/.dm/test_role/meta.role.json +13 -0
- dmart/sample/spaces/management/roles/.dm/world/meta.role.json +15 -0
- dmart/sample/spaces/management/roles.json +1 -0
- dmart/sample/spaces/management/schema/.dm/admin_notification_request/attachments.media/meta.ui_schema.json +10 -0
- dmart/sample/spaces/management/schema/.dm/admin_notification_request/attachments.media/ui_schema.json +32 -0
- dmart/sample/spaces/management/schema/.dm/admin_notification_request/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/api/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/folder_rendering/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/health_check/meta.schema.json +17 -0
- dmart/sample/spaces/management/schema/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/schema/.dm/meta_schema/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/metafile/meta.schema.json +14 -0
- dmart/sample/spaces/management/schema/.dm/notification/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/system_notification_request/attachments.media/meta.ui_schema.json +10 -0
- dmart/sample/spaces/management/schema/.dm/system_notification_request/attachments.media/ui_schema.json +32 -0
- dmart/sample/spaces/management/schema/.dm/system_notification_request/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/view/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/.dm/workflow/meta.schema.json +1 -0
- dmart/sample/spaces/management/schema/admin_notification_request.json +89 -0
- dmart/sample/spaces/management/schema/api.json +1 -0
- dmart/sample/spaces/management/schema/folder_rendering.json +238 -0
- dmart/sample/spaces/management/schema/health_check.json +8 -0
- dmart/sample/spaces/management/schema/meta_schema.json +74 -0
- dmart/sample/spaces/management/schema/metafile.json +153 -0
- dmart/sample/spaces/management/schema/notification.json +28 -0
- dmart/sample/spaces/management/schema/system_notification_request.json +57 -0
- dmart/sample/spaces/management/schema/view.json +23 -0
- dmart/sample/spaces/management/schema/workflow.json +87 -0
- dmart/sample/spaces/management/schema.json +1 -0
- dmart/sample/spaces/management/users/.dm/alibaba/meta.user.json +23 -0
- dmart/sample/spaces/management/users/.dm/anonymous/meta.user.json +18 -0
- dmart/sample/spaces/management/users/.dm/dmart/meta.user.json +26 -0
- dmart/sample/spaces/management/users/.dm/meta.folder.json +14 -0
- dmart/sample/spaces/management/workflows/.dm/channel/meta.content.json +1 -0
- dmart/sample/spaces/management/workflows/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/management/workflows/channel.json +148 -0
- dmart/sample/spaces/management/workflows.json +1 -0
- dmart/sample/spaces/maqola/.dm/meta.space.json +33 -0
- dmart/sample/spaces/personal/.dm/meta.space.json +24 -0
- dmart/sample/spaces/personal/people/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/personal/people/dmart/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/personal/people/dmart/messages/.dm/0b5f7e7f/meta.content.json +1 -0
- dmart/sample/spaces/personal/people/dmart/messages/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/personal/people/dmart/messages/.dm/mytest/meta.content.json +1 -0
- dmart/sample/spaces/personal/people/dmart/messages/0b5f7e7f.json +1 -0
- dmart/sample/spaces/personal/people/dmart/messages/mytest.json +1 -0
- dmart/sample/spaces/personal/people/dmart/notifications/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/personal/people/dmart/private/.dm/inner/meta.content.json +1 -0
- dmart/sample/spaces/personal/people/dmart/private/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/personal/people/dmart/private/inner.json +1 -0
- dmart/sample/spaces/personal/people/dmart/protected/.dm/avatar/meta.content.json +1 -0
- dmart/sample/spaces/personal/people/dmart/protected/.dm/meta.folder.json +1 -0
- dmart/sample/spaces/personal/people/dmart/protected/avatar.png +0 -0
- dmart/sample/spaces/personal/people/dmart/public/.dm/meta.folder.json +1 -0
- dmart/sample/test/.gitignore +2 -0
- dmart/sample/test/createcontent.json +9 -0
- dmart/sample/test/createmedia.json +9 -0
- dmart/sample/test/createmedia_entry.json +6 -0
- dmart/sample/test/createschema.json +8 -0
- dmart/sample/test/createschemawork.json +11 -0
- dmart/sample/test/createticket.json +13 -0
- dmart/sample/test/data.json +4 -0
- dmart/sample/test/deletecontent.json +12 -0
- dmart/sample/test/logo.jpeg +0 -0
- dmart/sample/test/my.jpg +0 -0
- dmart/sample/test/myticket.json +23 -0
- dmart/sample/test/resources.csv +12 -0
- dmart/sample/test/schema.json +16 -0
- dmart/sample/test/temp.json +1 -0
- dmart/sample/test/test.dmart +45 -0
- dmart/sample/test/ticket_schema.json +23 -0
- dmart/sample/test/ticket_workflow.json +85 -0
- dmart/sample/test/ticketbody.json +4 -0
- dmart/sample/test/ticketcontent.json +14 -0
- dmart/sample/test/updatecontent.json +20 -0
- dmart/sample/test/workflow_schema.json +68 -0
- dmart/scheduled_notification_handler.py +121 -0
- dmart/schema_migration.py +208 -0
- dmart/schema_modulate.py +192 -0
- dmart/set_admin_passwd.py +75 -0
- dmart/sync.py +202 -0
- dmart/test_utils.py +34 -0
- dmart/utils/__init__.py +0 -0
- dmart/utils/access_control.py +306 -0
- dmart/utils/async_request.py +8 -0
- dmart/utils/exporter.py +309 -0
- dmart/utils/firebase_notifier.py +57 -0
- dmart/utils/generate_email.py +37 -0
- dmart/utils/helpers.py +352 -0
- dmart/utils/hypercorn_config.py +12 -0
- dmart/utils/internal_error_code.py +60 -0
- dmart/utils/jwt.py +124 -0
- dmart/utils/logger.py +167 -0
- dmart/utils/middleware.py +99 -0
- dmart/utils/notification.py +75 -0
- dmart/utils/password_hashing.py +16 -0
- dmart/utils/plugin_manager.py +202 -0
- dmart/utils/query_policies_helper.py +128 -0
- dmart/utils/regex.py +44 -0
- dmart/utils/repository.py +529 -0
- dmart/utils/router_helper.py +19 -0
- dmart/utils/settings.py +212 -0
- dmart/utils/sms_notifier.py +21 -0
- dmart/utils/social_sso.py +67 -0
- dmart/utils/templates/activation.html.j2 +26 -0
- dmart/utils/templates/reminder.html.j2 +17 -0
- dmart/utils/ticket_sys_utils.py +203 -0
- dmart/utils/web_notifier.py +29 -0
- dmart/websocket.py +231 -0
- dmart-1.4.40.post8.dist-info/METADATA +75 -0
- dmart-1.4.40.post8.dist-info/RECORD +489 -0
- dmart-1.4.40.post8.dist-info/WHEEL +5 -0
- dmart-1.4.40.post8.dist-info/entry_points.txt +2 -0
- 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))
|