dmart 1.4.33__py3-none-any.whl → 1.4.36__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 +8 -0
- dmart/alembic/README +1 -0
- dmart/alembic/notes.txt +11 -0
- dmart/alembic/script.py.mako +28 -0
- dmart/alembic.ini +117 -0
- dmart/config.env.sample +27 -0
- dmart/conftest.py +13 -0
- dmart/curl.sh +196 -0
- dmart.py → dmart/dmart.py +47 -40
- dmart/hypercorn_config.toml +3 -0
- dmart/info.json +1 -0
- dmart/login_creds.sh +7 -0
- dmart/login_creds.sh.sample +7 -0
- main.py → dmart/main.py +4 -1
- dmart/manifest.sh +12 -0
- dmart/plugins/action_log/config.json +13 -0
- dmart/plugins/admin_notification_sender/config.json +13 -0
- dmart/plugins/ldap_manager/config.json +12 -0
- dmart/plugins/ldap_manager/dmart.schema +146 -0
- dmart/plugins/ldap_manager/slapd.conf +53 -0
- dmart/plugins/local_notification/config.json +13 -0
- dmart/plugins/realtime_updates_notifier/config.json +12 -0
- dmart/plugins/redis_db_update/config.json +13 -0
- dmart/plugins/resource_folders_creation/config.json +12 -0
- dmart/plugins/system_notification_sender/config.json +13 -0
- dmart/plugins/update_access_controls/config.json +12 -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/test_utils.py +34 -0
- {dmart-1.4.33.dist-info → dmart-1.4.36.dist-info}/METADATA +1 -1
- dmart-1.4.36.dist-info/RECORD +285 -0
- dmart-1.4.36.dist-info/entry_points.txt +2 -0
- dmart-1.4.36.dist-info/top_level.txt +1 -0
- dmart-1.4.33.dist-info/RECORD +0 -264
- dmart-1.4.33.dist-info/entry_points.txt +0 -2
- dmart-1.4.33.dist-info/top_level.txt +0 -24
- pytests/api_user_models_erros_test.py +0 -16
- pytests/api_user_models_requests_test.py +0 -98
- pytests/archive_test.py +0 -72
- pytests/base_test.py +0 -300
- pytests/get_settings_test.py +0 -14
- pytests/json_to_db_migration_test.py +0 -237
- pytests/service_test.py +0 -26
- pytests/test_info.py +0 -55
- pytests/test_status.py +0 -15
- utils/__init__.py +0 -0
- {alembic → dmart/alembic}/__init__.py +0 -0
- {alembic → dmart/alembic}/env.py +0 -0
- {alembic → dmart/alembic}/scripts/__init__.py +0 -0
- {alembic → dmart/alembic}/scripts/calculate_checksums.py +0 -0
- {alembic → dmart/alembic}/scripts/migration_f7a4949eed19.py +0 -0
- {alembic → dmart/alembic}/versions/0f3d2b1a7c21_add_authz_materialized_views.py +0 -0
- {alembic → dmart/alembic}/versions/10d2041b94d4_last_checksum_history.py +0 -0
- {alembic → dmart/alembic}/versions/1cf4e1ee3cb8_ext_permission_with_filter_fields_values.py +0 -0
- {alembic → dmart/alembic}/versions/26bfe19b49d4_rm_failedloginattempts.py +0 -0
- {alembic → dmart/alembic}/versions/3c8bca2219cc_add_otp_table.py +0 -0
- {alembic → dmart/alembic}/versions/6675fd9dfe42_remove_unique_from_sessions_table.py +0 -0
- {alembic → dmart/alembic}/versions/71bc1df82e6a_adding_user_last_login_at.py +0 -0
- {alembic → dmart/alembic}/versions/74288ccbd3b5_initial.py +0 -0
- {alembic → dmart/alembic}/versions/7520a89a8467_rm_activesession_table.py +0 -0
- {alembic → dmart/alembic}/versions/848b623755a4_make_created_nd_updated_at_required.py +0 -0
- {alembic → dmart/alembic}/versions/8640dcbebf85_add_notes_to_users.py +0 -0
- {alembic → dmart/alembic}/versions/91c94250232a_adding_fk_on_owner_shortname.py +0 -0
- {alembic → dmart/alembic}/versions/98ecd6f56f9a_ext_meta_with_owner_group_shortname.py +0 -0
- {alembic → dmart/alembic}/versions/9aae9138c4ef_indexing_created_at_updated_at.py +0 -0
- {alembic → dmart/alembic}/versions/__init__.py +0 -0
- {alembic → dmart/alembic}/versions/b53f916b3f6d_json_to_jsonb.py +0 -0
- {alembic → dmart/alembic}/versions/eb5f1ec65156_adding_user_locked_to_device.py +0 -0
- {alembic → dmart/alembic}/versions/f7a4949eed19_adding_query_policies_to_meta.py +0 -0
- {api → dmart/api}/__init__.py +0 -0
- {api → dmart/api}/info/__init__.py +0 -0
- {api → dmart/api}/info/router.py +0 -0
- {api → dmart/api}/managed/__init__.py +0 -0
- {api → dmart/api}/managed/router.py +0 -0
- {api → dmart/api}/managed/utils.py +0 -0
- {api → dmart/api}/public/__init__.py +0 -0
- {api → dmart/api}/public/router.py +0 -0
- {api → dmart/api}/qr/__init__.py +0 -0
- {api → dmart/api}/qr/router.py +0 -0
- {api → dmart/api}/user/__init__.py +0 -0
- {api → dmart/api}/user/model/__init__.py +0 -0
- {api → dmart/api}/user/model/errors.py +0 -0
- {api → dmart/api}/user/model/requests.py +0 -0
- {api → dmart/api}/user/model/responses.py +0 -0
- {api → dmart/api}/user/router.py +0 -0
- {api → dmart/api}/user/service.py +0 -0
- /bundler.py → /dmart/bundler.py +0 -0
- {config → dmart/config}/__init__.py +0 -0
- {config → dmart/config}/channels.json +0 -0
- {config → dmart/config}/notification.json +0 -0
- {cxb → dmart/cxb}/__init__.py +0 -0
- {cxb/client → dmart/cxb}/assets/@codemirror-Rn7_6DkE.js +0 -0
- {cxb/client → dmart/cxb}/assets/@edraj-CS4NwVbD.js +0 -0
- {cxb/client → dmart/cxb}/assets/@floating-ui-BwwcF-xh.js +0 -0
- {cxb/client → dmart/cxb}/assets/@formatjs-yKEsAtjs.js +0 -0
- {cxb/client → dmart/cxb}/assets/@fortawesome-DRW1UCdr.js +0 -0
- {cxb/client → dmart/cxb}/assets/@jsonquerylang-laKNoFFq.js +0 -0
- {cxb/client → dmart/cxb}/assets/@lezer-za4Q-8Ew.js +0 -0
- {cxb/client → dmart/cxb}/assets/@marijn-DXwl3gUT.js +0 -0
- {cxb/client → dmart/cxb}/assets/@popperjs-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/@replit--ERk53eB.js +0 -0
- {cxb/client → dmart/cxb}/assets/@roxi-CGMFK4i8.js +0 -0
- {cxb/client → dmart/cxb}/assets/@typewriter-cCzskkIv.js +0 -0
- {cxb/client → dmart/cxb}/assets/@zerodevx-BlBZjKxu.js +0 -0
- {cxb/client → dmart/cxb}/assets/@zerodevx-CVEpe6WZ.css +0 -0
- {cxb/client → dmart/cxb}/assets/BreadCrumbLite-DAhOx38v.js +0 -0
- {cxb/client → dmart/cxb}/assets/EntryRenderer-25YDhRen.js +0 -0
- {cxb/client → dmart/cxb}/assets/EntryRenderer-DXytdFp9.css +0 -0
- {cxb/client → dmart/cxb}/assets/ListView-BpAycA2h.js +0 -0
- {cxb/client → dmart/cxb}/assets/ListView-U8of-_c-.css +0 -0
- {cxb/client → dmart/cxb}/assets/Prism--hMplq-p.js +0 -0
- {cxb/client → dmart/cxb}/assets/Prism-Uh6uStUw.css +0 -0
- {cxb/client → dmart/cxb}/assets/Table2Cols-BsbwicQm.js +0 -0
- {cxb/client → dmart/cxb}/assets/_..-BvT6vdHa.css +0 -0
- {cxb/client → dmart/cxb}/assets/_...404_-fuLH_rX9.js +0 -0
- {cxb/client → dmart/cxb}/assets/_...fallback_-Ba_NLmAE.js +0 -0
- {cxb/client → dmart/cxb}/assets/_module-Bfk8MiCs.js +0 -0
- {cxb/client → dmart/cxb}/assets/_module-CEW0D5oI.js +0 -0
- {cxb/client → dmart/cxb}/assets/_module-Dgq0ZVtz.js +0 -0
- {cxb/client → dmart/cxb}/assets/ajv-Cpj98o6Y.js +0 -0
- {cxb/client → dmart/cxb}/assets/axios-CG2WSiiR.js +0 -0
- {cxb/client → dmart/cxb}/assets/clsx-B-dksMZM.js +0 -0
- {cxb/client → dmart/cxb}/assets/codemirror-wrapped-line-indent-DPhKvljI.js +0 -0
- {cxb/client → dmart/cxb}/assets/compare-C3AjiGFR.js +0 -0
- {cxb/client → dmart/cxb}/assets/compute-scroll-into-view-Bl8rNFhg.js +0 -0
- {cxb/client → dmart/cxb}/assets/consolite-DlCuI0F9.js +0 -0
- {cxb/client → dmart/cxb}/assets/crelt-C8TCjufn.js +0 -0
- {cxb/client → dmart/cxb}/assets/date-fns-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/deepmerge-rn4rBaHU.js +0 -0
- {cxb/client → dmart/cxb}/assets/dmart_services-AL6-IdDE.js +0 -0
- {cxb/client → dmart/cxb}/assets/downloadFile-D08i0YDh.js +0 -0
- {cxb/client → dmart/cxb}/assets/easy-signal-BiPFIK3O.js +0 -0
- {cxb/client → dmart/cxb}/assets/esm-env-rsSWfq8L.js +0 -0
- {cxb/client → dmart/cxb}/assets/export-OF_rTiXu.js +0 -0
- {cxb/client → dmart/cxb}/assets/fast-deep-equal-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/fast-diff-C-IidNf4.js +0 -0
- {cxb/client → dmart/cxb}/assets/fast-uri-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/flowbite-svelte-BLvjb-sa.js +0 -0
- {cxb/client → dmart/cxb}/assets/flowbite-svelte-CD54FDqW.css +0 -0
- {cxb/client → dmart/cxb}/assets/flowbite-svelte-icons-BI8GVhw_.js +0 -0
- {cxb/client → dmart/cxb}/assets/github-slugger-CQ4oX9Ud.js +0 -0
- {cxb/client → dmart/cxb}/assets/global-igKv-1g9.js +0 -0
- {cxb/client → dmart/cxb}/assets/hookar-BMRD9G9H.js +0 -0
- {cxb/client → dmart/cxb}/assets/immutable-json-patch-DtRO2E_S.js +0 -0
- {cxb/client → dmart/cxb}/assets/import-1vE3gBat.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-B-eTh-ZX.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-BVyxzKtH.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-BdeNM69f.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-C6cPO4op.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-CC-A1ipE.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-CTxJ-lDp.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-Cd-F5j_k.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-D742rwaM.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-DTfhnhwd.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-DdXRK7n9.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-DtiCmB4o.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-NBrXBlLA.css +0 -0
- {cxb/client → dmart/cxb}/assets/index-ac-Buu_H.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-iYkH7C67.js +0 -0
- {cxb/client → dmart/cxb}/assets/info-B986lRiM.js +0 -0
- {cxb/client → dmart/cxb}/assets/intl-messageformat-Dc5UU-HB.js +0 -0
- {cxb/client → dmart/cxb}/assets/jmespath-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/json-schema-traverse-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/json-source-map-DRgZidqy.js +0 -0
- {cxb/client → dmart/cxb}/assets/jsonpath-plus-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/jsonrepair-B30Dx381.js +0 -0
- {cxb/client → dmart/cxb}/assets/lodash-es-DZVAA2ox.js +0 -0
- {cxb/client → dmart/cxb}/assets/marked-DKjyhwJX.js +0 -0
- {cxb/client → dmart/cxb}/assets/marked-gfm-heading-id-U5zO829x.js +0 -0
- {cxb/client → dmart/cxb}/assets/marked-mangle-CDMeiHC6.js +0 -0
- {cxb/client → dmart/cxb}/assets/memoize-one-BdPwpGay.js +0 -0
- {cxb/client → dmart/cxb}/assets/natural-compare-lite-Bg2Xcf-o.js +0 -0
- {cxb/client → dmart/cxb}/assets/pagination-svelte-D5CyoiE_.js +0 -0
- {cxb/client → dmart/cxb}/assets/pagination-svelte-v10nAbbM.css +0 -0
- {cxb/client → dmart/cxb}/assets/plantuml-encoder-C47mzt9T.js +0 -0
- {cxb/client → dmart/cxb}/assets/prismjs-DTUiLGJu.js +0 -0
- {cxb/client → dmart/cxb}/assets/profile-BUf-tKMe.js +0 -0
- {cxb/client → dmart/cxb}/assets/query-CNmXTsgf.js +0 -0
- {cxb/client → dmart/cxb}/assets/queryHelpers-C9iBWwqe.js +0 -0
- {cxb/client → dmart/cxb}/assets/scroll-into-view-if-needed-KR58zyjF.js +0 -0
- {cxb/client → dmart/cxb}/assets/spaces-0oyGvpii.js +0 -0
- {cxb/client → dmart/cxb}/assets/style-mod-Bs6eFhZE.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-B2XmcTi_.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-awesome-COLlx0DN.css +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-awesome-DhnMA6Q_.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-datatables-net-CY7LBj6I.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-floating-ui-BlS3sOAQ.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-i18n-CT2KkQaN.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-jsoneditor-BzfX6Usi.css +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-jsoneditor-CUGSvWId.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-select-CegQKzqH.css +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-select-CjHAt_85.js +0 -0
- {cxb/client → dmart/cxb}/assets/tailwind-merge-CJvxXMcu.js +0 -0
- {cxb/client → dmart/cxb}/assets/tailwind-variants-Cj20BoQ3.js +0 -0
- {cxb/client → dmart/cxb}/assets/toast-B9WDyfyI.js +0 -0
- {cxb/client → dmart/cxb}/assets/tslib-pJfR_DrR.js +0 -0
- {cxb/client → dmart/cxb}/assets/typewriter-editor-DkTVIJdm.js +0 -0
- {cxb/client → dmart/cxb}/assets/user-DeK_NB5v.js +0 -0
- {cxb/client → dmart/cxb}/assets/vanilla-picker-l5rcX3cq.js +0 -0
- {cxb/client → dmart/cxb}/assets/w3c-keyname-Vcq4gwWv.js +0 -0
- {cxb/client → dmart/cxb}/config.json +0 -0
- {cxb/client → dmart/cxb}/config.sample.json +0 -0
- {cxb/client → dmart/cxb}/favicon.ico +0 -0
- {cxb/client → dmart/cxb}/favicon.png +0 -0
- {cxb/client → dmart/cxb}/index.html +0 -0
- {data_adapters → dmart/data_adapters}/__init__.py +0 -0
- {data_adapters → dmart/data_adapters}/adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/base_data_adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/file/__init__.py +0 -0
- {data_adapters → dmart/data_adapters}/file/adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/file/adapter_helpers.py +0 -0
- {data_adapters → dmart/data_adapters}/file/archive.py +0 -0
- {data_adapters → dmart/data_adapters}/file/create_index.py +0 -0
- {data_adapters → dmart/data_adapters}/file/create_users_folders.py +0 -0
- {data_adapters → dmart/data_adapters}/file/custom_validations.py +0 -0
- {data_adapters → dmart/data_adapters}/file/drop_index.py +0 -0
- {data_adapters → dmart/data_adapters}/file/health_check.py +0 -0
- {data_adapters → dmart/data_adapters}/file/redis_services.py +0 -0
- {data_adapters → dmart/data_adapters}/helpers.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/__init__.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/adapter_helpers.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/create_tables.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/create_users_folders.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/db_to_json_migration.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/health_check_sql.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/json_to_db_migration.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/update_query_policies.py +0 -0
- /data_generator.py → /dmart/data_generator.py +0 -0
- /get_settings.py → /dmart/get_settings.py +0 -0
- {languages → dmart/languages}/__init__.py +0 -0
- {languages → dmart/languages}/arabic.json +0 -0
- {languages → dmart/languages}/english.json +0 -0
- {languages → dmart/languages}/kurdish.json +0 -0
- {languages → dmart/languages}/loader.py +0 -0
- /migrate.py → /dmart/migrate.py +0 -0
- {models → dmart/models}/__init__.py +0 -0
- {models → dmart/models}/api.py +0 -0
- {models → dmart/models}/core.py +0 -0
- {models → dmart/models}/enums.py +0 -0
- /password_gen.py → /dmart/password_gen.py +0 -0
- {plugins → dmart/plugins}/__init__.py +0 -0
- {plugins → dmart/plugins}/action_log/__init__.py +0 -0
- {plugins → dmart/plugins}/action_log/plugin.py +0 -0
- {plugins → dmart/plugins}/admin_notification_sender/__init__.py +0 -0
- {plugins → dmart/plugins}/admin_notification_sender/plugin.py +0 -0
- {plugins → dmart/plugins}/ldap_manager/__init__.py +0 -0
- {plugins → dmart/plugins}/ldap_manager/plugin.py +0 -0
- {plugins → dmart/plugins}/local_notification/__init__.py +0 -0
- {plugins → dmart/plugins}/local_notification/plugin.py +0 -0
- {plugins → dmart/plugins}/realtime_updates_notifier/__init__.py +0 -0
- {plugins → dmart/plugins}/realtime_updates_notifier/plugin.py +0 -0
- {plugins → dmart/plugins}/redis_db_update/__init__.py +0 -0
- {plugins → dmart/plugins}/redis_db_update/plugin.py +0 -0
- {plugins → dmart/plugins}/resource_folders_creation/__init__.py +0 -0
- {plugins → dmart/plugins}/resource_folders_creation/plugin.py +0 -0
- {plugins → dmart/plugins}/system_notification_sender/__init__.py +0 -0
- {plugins → dmart/plugins}/system_notification_sender/plugin.py +0 -0
- {plugins → dmart/plugins}/update_access_controls/__init__.py +0 -0
- {plugins → dmart/plugins}/update_access_controls/plugin.py +0 -0
- /run_notification_campaign.py → /dmart/run_notification_campaign.py +0 -0
- /scheduled_notification_handler.py → /dmart/scheduled_notification_handler.py +0 -0
- /schema_migration.py → /dmart/schema_migration.py +0 -0
- /schema_modulate.py → /dmart/schema_modulate.py +0 -0
- /set_admin_passwd.py → /dmart/set_admin_passwd.py +0 -0
- /sync.py → /dmart/sync.py +0 -0
- {pytests → dmart/utils}/__init__.py +0 -0
- {utils → dmart/utils}/access_control.py +0 -0
- {utils → dmart/utils}/async_request.py +0 -0
- {utils → dmart/utils}/exporter.py +0 -0
- {utils → dmart/utils}/firebase_notifier.py +0 -0
- {utils → dmart/utils}/generate_email.py +0 -0
- {utils → dmart/utils}/helpers.py +0 -0
- {utils → dmart/utils}/hypercorn_config.py +0 -0
- {utils → dmart/utils}/internal_error_code.py +0 -0
- {utils → dmart/utils}/jwt.py +0 -0
- {utils → dmart/utils}/logger.py +0 -0
- {utils → dmart/utils}/middleware.py +0 -0
- {utils → dmart/utils}/notification.py +0 -0
- {utils → dmart/utils}/password_hashing.py +0 -0
- {utils → dmart/utils}/plugin_manager.py +0 -0
- {utils → dmart/utils}/query_policies_helper.py +0 -0
- {utils → dmart/utils}/regex.py +0 -0
- {utils → dmart/utils}/repository.py +0 -0
- {utils → dmart/utils}/router_helper.py +0 -0
- {utils → dmart/utils}/settings.py +0 -0
- {utils → dmart/utils}/sms_notifier.py +0 -0
- {utils → dmart/utils}/social_sso.py +0 -0
- {utils → dmart/utils}/templates/activation.html.j2 +0 -0
- {utils → dmart/utils}/templates/reminder.html.j2 +0 -0
- {utils → dmart/utils}/ticket_sys_utils.py +0 -0
- {utils → dmart/utils}/web_notifier.py +0 -0
- /websocket.py → /dmart/websocket.py +0 -0
- {dmart-1.4.33.dist-info → dmart-1.4.36.dist-info}/WHEEL +0 -0
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from uuid import uuid4
|
|
3
|
-
import pytest
|
|
4
|
-
import os
|
|
5
|
-
import json
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from sqlmodel import Session, create_engine, text, SQLModel
|
|
8
|
-
from data_adapters.sql.create_tables import Attachments, Entries, Spaces, Histories
|
|
9
|
-
from sqlalchemy.exc import OperationalError
|
|
10
|
-
from utils.settings import settings
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def subpath_checker(subpath: str):
|
|
14
|
-
if subpath.endswith("/"):
|
|
15
|
-
subpath = subpath[:-1]
|
|
16
|
-
if not subpath.startswith("/"):
|
|
17
|
-
subpath = '/' + subpath
|
|
18
|
-
return subpath
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def connect_with_retry(engine, retries=5, delay=2):
|
|
22
|
-
"""
|
|
23
|
-
Try to connect to the database with retries.
|
|
24
|
-
"""
|
|
25
|
-
for attempt in range(retries):
|
|
26
|
-
try:
|
|
27
|
-
with engine.connect() as _:
|
|
28
|
-
print(f"Connected to the database on attempt {attempt + 1}")
|
|
29
|
-
return
|
|
30
|
-
except OperationalError as e:
|
|
31
|
-
print(f"Connection attempt {attempt + 1} failed: {e}")
|
|
32
|
-
time.sleep(delay)
|
|
33
|
-
raise Exception("Could not connect to the database after multiple attempts")
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@pytest.fixture(scope="module")
|
|
37
|
-
def setup_database():
|
|
38
|
-
if settings.active_data_db == "file":
|
|
39
|
-
pytest.skip("Skipping test for file-based database")
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
# Use the settings to connect with the main `postgres` user
|
|
43
|
-
postgresql_url = f"{settings.database_driver.replace('+asyncpg','+psycopg')}://{settings.database_username}:{settings.database_password}@{settings.database_host}:{settings.database_port}"
|
|
44
|
-
engine = create_engine(f"{postgresql_url}/postgres", echo=False, isolation_level="AUTOCOMMIT")
|
|
45
|
-
|
|
46
|
-
# Create the database
|
|
47
|
-
with Session(engine) as session:
|
|
48
|
-
try:
|
|
49
|
-
session.exec(text(f"DROP DATABASE IF EXISTS {settings.database_name}"))
|
|
50
|
-
session.commit()
|
|
51
|
-
session.exec(text(f"CREATE DATABASE {settings.database_name}"))
|
|
52
|
-
session.commit() # Ensure the transaction is fully committed
|
|
53
|
-
print(f"Database {settings.database_name} created successfully")
|
|
54
|
-
except Exception as e:
|
|
55
|
-
print(f"Database creation failed: {e}")
|
|
56
|
-
|
|
57
|
-
# Add a small delay to ensure the database is fully ready
|
|
58
|
-
time.sleep(2)
|
|
59
|
-
|
|
60
|
-
yield
|
|
61
|
-
|
|
62
|
-
# Drop the database after tests
|
|
63
|
-
with Session(engine) as session:
|
|
64
|
-
try:
|
|
65
|
-
session.exec(text(f"DROP DATABASE IF EXISTS {settings.database_name}"))
|
|
66
|
-
session.commit()
|
|
67
|
-
print(f"Database {settings.database_name} dropped successfully")
|
|
68
|
-
except Exception as e:
|
|
69
|
-
print(f"Database deletion failed: {e}")
|
|
70
|
-
|
|
71
|
-
engine.dispose()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@pytest.fixture(scope="module")
|
|
75
|
-
def setup_environment(setup_database):
|
|
76
|
-
if settings.active_data_db == "file":
|
|
77
|
-
pytest.skip("Skipping test for file-based database")
|
|
78
|
-
return
|
|
79
|
-
|
|
80
|
-
# Set the database name from settings
|
|
81
|
-
driver = settings.database_driver.replace('+asyncpg', '+psycopg')
|
|
82
|
-
postgresql_url = f"{driver}://{settings.database_username}:{settings.database_password}@{settings.database_host}:{settings.database_port}"
|
|
83
|
-
engine = create_engine(f"{postgresql_url}/{settings.database_name}", echo=False)
|
|
84
|
-
|
|
85
|
-
# Retry connecting to the newly created database
|
|
86
|
-
connect_with_retry(engine)
|
|
87
|
-
|
|
88
|
-
# Generate tables after ensuring connection
|
|
89
|
-
postgresql_url = f"{driver}://{settings.database_username}:{settings.database_password}@{settings.database_host}:{settings.database_port}/{settings.database_name}"
|
|
90
|
-
engine = create_engine(postgresql_url, echo=False)
|
|
91
|
-
SQLModel.metadata.create_all(engine)
|
|
92
|
-
|
|
93
|
-
yield engine
|
|
94
|
-
|
|
95
|
-
engine.dispose()
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def test_json_to_db_migration(setup_environment):
|
|
99
|
-
if settings.active_data_db == "file":
|
|
100
|
-
pytest.skip("Skipping test for file-based database")
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
engine = setup_environment
|
|
104
|
-
|
|
105
|
-
# Create a complex mock directory structure and files for different entry types
|
|
106
|
-
os.makedirs('/tmp/test_space/.dm', exist_ok=True)
|
|
107
|
-
with open('/tmp/test_space/.dm/meta.space.json', 'w') as f:
|
|
108
|
-
json.dump({"key": "value"}, f)
|
|
109
|
-
|
|
110
|
-
# Create more directories and files for the migration
|
|
111
|
-
os.makedirs('/tmp/test_space/dir1', exist_ok=True)
|
|
112
|
-
with open('/tmp/test_space/dir1/history.jsonl', 'w') as f:
|
|
113
|
-
f.write(json.dumps({"key": "history"}) + '\n')
|
|
114
|
-
|
|
115
|
-
# Create attachments folder and files
|
|
116
|
-
os.makedirs('/tmp/test_space/dir1/attachments', exist_ok=True)
|
|
117
|
-
with open('/tmp/test_space/dir1/attachments/meta.attachments.json', 'w') as f:
|
|
118
|
-
json.dump({
|
|
119
|
-
"uuid": str(uuid4()),
|
|
120
|
-
"space_name": "test_space",
|
|
121
|
-
"subpath": "/dir1",
|
|
122
|
-
"acl": [],
|
|
123
|
-
"relationships": [],
|
|
124
|
-
"payload": {"body": "attachment content"}
|
|
125
|
-
}, f)
|
|
126
|
-
|
|
127
|
-
# Create ticket-related file
|
|
128
|
-
with open('/tmp/test_space/dir1/meta.ticket.json', 'w') as f:
|
|
129
|
-
json.dump({
|
|
130
|
-
"state": "open",
|
|
131
|
-
"is_open": True,
|
|
132
|
-
"reporter": "user1",
|
|
133
|
-
"subpath": "/dir1/ticket"
|
|
134
|
-
}, f)
|
|
135
|
-
|
|
136
|
-
# Create user meta file
|
|
137
|
-
with open('/tmp/test_space/.dm/meta.user.json', 'w') as f:
|
|
138
|
-
json.dump({
|
|
139
|
-
"resource_type": "user",
|
|
140
|
-
"firebase_token": "firebase_token",
|
|
141
|
-
"language": "en"
|
|
142
|
-
}, f)
|
|
143
|
-
|
|
144
|
-
# Create role meta file
|
|
145
|
-
with open('/tmp/test_space/.dm/meta.role.json', 'w') as f:
|
|
146
|
-
json.dump({
|
|
147
|
-
"resource_type": "role",
|
|
148
|
-
"permissions": ["read", "write"]
|
|
149
|
-
}, f)
|
|
150
|
-
|
|
151
|
-
# Create permission meta file
|
|
152
|
-
with open('/tmp/test_space/.dm/meta.permission.json', 'w') as f:
|
|
153
|
-
json.dump({
|
|
154
|
-
"resource_type": "permission",
|
|
155
|
-
"subpaths": {"read": "/read", "write": "/write"},
|
|
156
|
-
"resource_types": ["user", "role"]
|
|
157
|
-
}, f)
|
|
158
|
-
|
|
159
|
-
# Run the migration script
|
|
160
|
-
try:
|
|
161
|
-
with Session(engine) as session:
|
|
162
|
-
for root, dirs, _ in os.walk('/tmp/test_space'):
|
|
163
|
-
tmp = root.replace('/tmp/test_space', '')
|
|
164
|
-
if tmp == '':
|
|
165
|
-
continue
|
|
166
|
-
if tmp[0] == '/':
|
|
167
|
-
tmp = tmp[1:]
|
|
168
|
-
space_name = tmp.split('/')[0]
|
|
169
|
-
subpath = '/'.join(tmp.split('/')[1:])
|
|
170
|
-
if space_name == '..':
|
|
171
|
-
continue
|
|
172
|
-
|
|
173
|
-
if space_name.startswith('.git'):
|
|
174
|
-
continue
|
|
175
|
-
|
|
176
|
-
if subpath == '' or subpath == '/':
|
|
177
|
-
subpath = '/'
|
|
178
|
-
p = os.path.join(root, '.dm', 'meta.space.json')
|
|
179
|
-
entry = {}
|
|
180
|
-
if Path(p).is_file():
|
|
181
|
-
entry = json.load(open(p))
|
|
182
|
-
entry['space_name'] = space_name
|
|
183
|
-
entry['subpath'] = '/'
|
|
184
|
-
session.add(Spaces.model_validate(entry))
|
|
185
|
-
continue
|
|
186
|
-
|
|
187
|
-
subpath = subpath.replace('.dm', '')
|
|
188
|
-
if subpath != '/' and subpath.endswith('/'):
|
|
189
|
-
subpath = subpath[:-1]
|
|
190
|
-
|
|
191
|
-
if subpath == '':
|
|
192
|
-
subpath = '/'
|
|
193
|
-
|
|
194
|
-
for dir in dirs:
|
|
195
|
-
for file in os.listdir(os.path.join(root, dir)):
|
|
196
|
-
if not file.startswith('meta'):
|
|
197
|
-
if file == 'history.jsonl':
|
|
198
|
-
lines = open(os.path.join(root, dir, file), 'r').readlines()
|
|
199
|
-
for line in lines:
|
|
200
|
-
history = json.loads(line)
|
|
201
|
-
history['shortname'] = dir
|
|
202
|
-
history['space_name'] = space_name
|
|
203
|
-
history['subpath'] = subpath_checker(subpath)
|
|
204
|
-
session.add(Histories.model_validate(history))
|
|
205
|
-
continue
|
|
206
|
-
|
|
207
|
-
p = os.path.join(root, dir, file)
|
|
208
|
-
if Path(p).is_file():
|
|
209
|
-
if 'attachments' in p:
|
|
210
|
-
_attachment = json.load(open(os.path.join(root, dir, file)))
|
|
211
|
-
_attachment['space_name'] = space_name
|
|
212
|
-
_attachment['uuid'] = _attachment.get('uuid', uuid4())
|
|
213
|
-
_attachment['subpath'] = subpath_checker(_attachment['subpath'])
|
|
214
|
-
session.add(Attachments.model_validate(_attachment))
|
|
215
|
-
elif file.endswith('.json'):
|
|
216
|
-
entry = json.load(open(p))
|
|
217
|
-
entry['space_name'] = space_name
|
|
218
|
-
entry['subpath'] = subpath_checker(subpath)
|
|
219
|
-
session.add(Entries.model_validate(entry))
|
|
220
|
-
session.commit()
|
|
221
|
-
assert True # Assert that the migration completes without error
|
|
222
|
-
except Exception as e:
|
|
223
|
-
print(f"Migration failed: {e}")
|
|
224
|
-
assert False # Fail the test if there is any exception
|
|
225
|
-
|
|
226
|
-
# Clean up the mock directory structure
|
|
227
|
-
os.remove('/tmp/test_space/.dm/meta.space.json')
|
|
228
|
-
os.remove('/tmp/test_space/dir1/history.jsonl')
|
|
229
|
-
os.remove('/tmp/test_space/dir1/attachments/meta.attachments.json')
|
|
230
|
-
os.remove('/tmp/test_space/dir1/meta.ticket.json')
|
|
231
|
-
os.remove('/tmp/test_space/.dm/meta.user.json')
|
|
232
|
-
os.remove('/tmp/test_space/.dm/meta.role.json')
|
|
233
|
-
os.remove('/tmp/test_space/.dm/meta.permission.json')
|
|
234
|
-
os.rmdir('/tmp/test_space/dir1/attachments')
|
|
235
|
-
os.rmdir('/tmp/test_space/.dm')
|
|
236
|
-
os.rmdir('/tmp/test_space/dir1')
|
|
237
|
-
os.rmdir('/tmp/test_space')
|
pytests/service_test.py
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from api.user.service import gen_alphanumeric
|
|
2
|
-
import pytest
|
|
3
|
-
|
|
4
|
-
@pytest.mark.run(order=9)
|
|
5
|
-
def test_gen_alphanumeric_length():
|
|
6
|
-
# Test default length
|
|
7
|
-
result = gen_alphanumeric()
|
|
8
|
-
assert len(result) == 16, "Default length should be 16"
|
|
9
|
-
|
|
10
|
-
# Test custom length
|
|
11
|
-
length = 32
|
|
12
|
-
result = gen_alphanumeric(length)
|
|
13
|
-
assert len(result) == length, f"Length should be {length}"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@pytest.mark.run(order=9)
|
|
17
|
-
def test_gen_alphanumeric_characters():
|
|
18
|
-
result = gen_alphanumeric()
|
|
19
|
-
assert all(c.isalnum() for c in result), "Result should only contain alphanumeric characters"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@pytest.mark.run(order=9)
|
|
23
|
-
def test_gen_alphanumeric_unique():
|
|
24
|
-
num_samples = 100
|
|
25
|
-
samples = {gen_alphanumeric() for _ in range(num_samples)}
|
|
26
|
-
assert len(samples) == num_samples, "Generated strings should be unique"
|
pytests/test_info.py
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
from httpx import AsyncClient
|
|
2
|
-
from pytests.base_test import get_superman_cookie
|
|
3
|
-
from fastapi import status
|
|
4
|
-
import pytest
|
|
5
|
-
from utils.internal_error_code import InternalErrorCode
|
|
6
|
-
from utils.jwt import sign_jwt
|
|
7
|
-
from utils.settings import settings
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@pytest.mark.run(order=6)
|
|
12
|
-
@pytest.mark.anyio
|
|
13
|
-
async def test_info_me(client: AsyncClient) -> None:
|
|
14
|
-
|
|
15
|
-
client.cookies.set("auth_token", await get_superman_cookie(client))
|
|
16
|
-
response = await client.get("/info/me")
|
|
17
|
-
assert response.status_code == status.HTTP_200_OK
|
|
18
|
-
json_response = response.json()
|
|
19
|
-
assert json_response["status"] == "success"
|
|
20
|
-
|
|
21
|
-
@pytest.mark.run(order=6)
|
|
22
|
-
@pytest.mark.anyio
|
|
23
|
-
async def test_info_manifest(client: AsyncClient) -> None:
|
|
24
|
-
|
|
25
|
-
client.cookies.set("auth_token", await get_superman_cookie(client))
|
|
26
|
-
response = await client.get("/info/manifest")
|
|
27
|
-
assert response.status_code == status.HTTP_200_OK
|
|
28
|
-
json_response = response.json()
|
|
29
|
-
assert json_response["status"] == "success"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@pytest.mark.run(order=6)
|
|
33
|
-
@pytest.mark.anyio
|
|
34
|
-
async def test_get_settings_should_pass(client: AsyncClient) -> None:
|
|
35
|
-
client.cookies.set("auth_token", await get_superman_cookie(client))
|
|
36
|
-
response = await client.get("/info/settings")
|
|
37
|
-
assert response.status_code == status.HTTP_200_OK
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# @pytest.mark.run(order=6)
|
|
41
|
-
# @pytest.mark.anyio
|
|
42
|
-
# async def test_in_loop_tasks(client: AsyncClient) -> None:
|
|
43
|
-
# client.cookies.set("auth_token", await get_superman_cookie(client))
|
|
44
|
-
# response = await client.get("/info/in-loop-tasks")
|
|
45
|
-
# assert response.status_code == status.HTTP_200_OK
|
|
46
|
-
# json_response = response.json()
|
|
47
|
-
# assert json_response["status"] == "success"
|
|
48
|
-
# assert "tasks_count" in json_response["attributes"]
|
|
49
|
-
# assert isinstance(json_response["attributes"]["tasks_count"], int)
|
|
50
|
-
# assert "tasks" in json_response["attributes"]
|
|
51
|
-
# assert isinstance(json_response["attributes"]["tasks"], list)
|
|
52
|
-
# for task in json_response["attributes"]["tasks"]:
|
|
53
|
-
# assert "name" in task
|
|
54
|
-
# assert "coroutine" in task
|
|
55
|
-
# assert "stack" in task
|
pytests/test_status.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# from pytests.base_test import client
|
|
3
|
-
from fastapi import status
|
|
4
|
-
from httpx import AsyncClient
|
|
5
|
-
import pytest
|
|
6
|
-
|
|
7
|
-
# @pytest.mark.asyncio(scope="session")
|
|
8
|
-
@pytest.mark.anyio
|
|
9
|
-
async def test_sanity(client: AsyncClient) -> None:
|
|
10
|
-
# async with my_client as client:
|
|
11
|
-
response = await client.get("/")
|
|
12
|
-
assert response.status_code == status.HTTP_200_OK
|
|
13
|
-
json_response = response.json()
|
|
14
|
-
assert json_response["status"] == "success"
|
|
15
|
-
|
utils/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
{alembic → dmart/alembic}/env.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{api → dmart/api}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{api → dmart/api}/info/router.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{api → dmart/api}/qr/__init__.py
RENAMED
|
File without changes
|
{api → dmart/api}/qr/router.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{api → dmart/api}/user/router.py
RENAMED
|
File without changes
|
|
File without changes
|
/bundler.py → /dmart/bundler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cxb → dmart/cxb}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|