mage-ai 0.9.32__py3-none-any.whl → 0.9.34__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.
Potentially problematic release.
This version of mage-ai might be problematic. Click here for more details.
- mage_ai/api/constants.py +37 -2
- mage_ai/api/errors.py +9 -5
- mage_ai/api/middleware.py +2 -2
- mage_ai/api/mixins/__init__.py +0 -0
- mage_ai/api/mixins/result_set.py +65 -0
- mage_ai/api/operations/base.py +41 -11
- mage_ai/api/operations/constants.py +7 -6
- mage_ai/api/parsers/BaseParser.py +6 -4
- mage_ai/api/parsers/PipelineScheduleParser.py +36 -2
- mage_ai/api/policies/BackfillPolicy.py +1 -0
- mage_ai/api/policies/BasePolicy.py +229 -40
- mage_ai/api/policies/PermissionPolicy.py +17 -0
- mage_ai/api/policies/PipelineSchedulePolicy.py +18 -2
- mage_ai/api/policies/RolePermissionPolicy.py +2 -1
- mage_ai/api/policies/RolePolicy.py +3 -0
- mage_ai/api/policies/SessionPolicy.py +36 -1
- mage_ai/api/policies/StatusPolicy.py +46 -3
- mage_ai/api/policies/UserPolicy.py +25 -2
- mage_ai/api/policies/mixins/__init__.py +0 -0
- mage_ai/api/policies/mixins/user_permissions.py +241 -0
- mage_ai/api/presenters/PermissionPresenter.py +35 -8
- mage_ai/api/presenters/RolePresenter.py +29 -12
- mage_ai/api/presenters/StatusPresenter.py +11 -0
- mage_ai/api/presenters/UserPresenter.py +21 -24
- mage_ai/api/resources/BaseResource.py +24 -9
- mage_ai/api/resources/BlockResource.py +3 -2
- mage_ai/api/resources/DatabaseResource.py +2 -2
- mage_ai/api/resources/PermissionResource.py +65 -3
- mage_ai/api/resources/Resource.py +8 -1
- mage_ai/api/resources/RolePermissionResource.py +23 -0
- mage_ai/api/resources/RoleResource.py +75 -4
- mage_ai/api/resources/StatusResource.py +34 -0
- mage_ai/api/resources/UserResource.py +35 -4
- mage_ai/api/result_set.py +8 -1
- mage_ai/authentication/permissions/constants.py +78 -0
- mage_ai/data_integrations/destinations/constants.py +1 -0
- mage_ai/data_integrations/utils/config.py +9 -0
- mage_ai/data_integrations/utils/scheduler.py +16 -7
- mage_ai/data_preparation/models/block/__init__.py +56 -16
- mage_ai/data_preparation/models/block/data_integration/mixins.py +92 -1
- mage_ai/data_preparation/models/block/data_integration/utils.py +5 -5
- mage_ai/data_preparation/models/block/integration/__init__.py +12 -7
- mage_ai/data_preparation/models/block/sql/__init__.py +5 -2
- mage_ai/data_preparation/models/block/sql/utils/shared.py +15 -1
- mage_ai/data_preparation/models/pipelines/interactions.py +15 -0
- mage_ai/data_preparation/shared/secrets.py +7 -17
- mage_ai/data_preparation/templates/data_exporters/streaming/google_cloud_pubsub.yaml +5 -0
- mage_ai/data_preparation/templates/repo/metadata.yaml +5 -0
- mage_ai/io/druid.py +9 -5
- mage_ai/io/mssql.py +52 -30
- mage_ai/io/postgres.py +1 -0
- mage_ai/io/sql.py +15 -1
- mage_ai/orchestration/db/models/oauth.py +181 -17
- mage_ai/orchestration/db/models/schedules.py +11 -0
- mage_ai/presenters/interactions/constants.py +1 -0
- mage_ai/presenters/pages/loaders/pipeline_schedules.py +9 -3
- mage_ai/server/api/base.py +16 -6
- mage_ai/server/api/v1.py +2 -1
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/_next/static/PBVuphyo_muEAj347ZP_b/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1124-d8fc76201b83b376.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{1749-9ec0f4709f5a9284.js → 1749-a6bdce4ee8a09bce.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1769-613e23e361eb5bce.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1821-953efd0da290d25f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2327-1a797c758f8b064a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2677-a85c5a72bb695304.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/3419-6c8ec8db8c398c12.js → frontend_dist/_next/static/chunks/3419-0df6c5ef72f2e672.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3684-e1a713b7c16f0151.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/3859-3501cdba0a33f9f2.js → frontend_dist/_next/static/chunks/3859-ba594d21a1260cd2.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/4636-84f545d1d238df13.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/4839-963da65cea58054f.js → frontend_dist/_next/static/chunks/4839-e5fe343a369734bc.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5457-97433bc45b42a88a.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/5499-63667ad5a785dba5.js → frontend_dist/_next/static/chunks/5499-b74459f6be5f9229.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6043-6ea109833b88eb1d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/6333-ca4cd6a73a597a40.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7022-80d082a1d7fd1234.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7361-25f211ef377e5958.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/8013-1d6b1f7c13264cb4.js → frontend_dist/_next/static/chunks/8013-e67c71ddea072a20.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8146-941c5155c3bfcc35.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9161-837b653aa849a76f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9264-5730e4e059db40a8.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-752d991f239a128f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{block-layout-a624972d126a3dbd.js → block-layout-a27a28d2a615e364.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-98e27a4d7bd0da47.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/{[...slug]-a95787fe1695f493.js → [...slug]-9eb5dad57da13efd.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-data-products-0d55711df91a78d0.js → global-data-products-26909dec66f00231.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-b9eea6abc676ca81.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/[user]-11c601c6ef07fe86.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/new-ae6083077c9c1c41.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-bfce0ee677d57206.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-476c921d62f565fc.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/overview-9bc34ef66d84330a.js → frontend_dist/_next/static/chunks/pages/overview-2ec6b17e45a52be8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-605918f3a5c1aac4.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-84ec3ab0770bcd68.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ee65a62ed166bd85.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-2402004a19a6ad53.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-9a5b4768a640cd68.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-8781db69f19759a1.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-d7fd4857579e2b00.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-bd4bd009146bab36.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-234007c99efdccf6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-8405a83adeaa8ff5.js → block-runs-da7510d4b277e47b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runtime-98aa0840a00cc661.js → block-runtime-eae853ff34b09481.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-0fb48e1cc51f78b2.js → monitors-a057b17847b82468.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/{[run]-845c1f010d5ec380.js → [run]-99d11c86f8b15369.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-9255f85760e1f57a.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-3f0980d8810a540b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{settings-187ac359020704e1.js → settings-9edf75d03460aaeb.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-c52d0c49439ec620.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-e7692e54979f037d.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-7b3b57523b226a0e.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-cb6a3bcaf4fa1a81.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-5eff96c149584e87.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{pipelines-efc080913a247e99.js → pipelines-270b912e1ac189b5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-2058d022972cdea4.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/[...slug]-1a95628ea8d0d846.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions-cb1cdf5f8e5bf9c5.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-58978256db4efbda.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/[...slug]-9ddd7eb842d5a911.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-1694c5eb1acbcf30.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-6850e854fbedbb61.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/[...slug]-5061c073e1c0de07.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-f551c5665bfd3494.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-6fe3657070f98aca.js → frontend_dist/_next/static/chunks/pages/sign-in-e779dbab123e626e.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/[...slug]-935113d252ada806.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/templates-25b6d24cfa81c306.js → frontend_dist/_next/static/chunks/pages/templates-7079d637e396f2a8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/terminal-67fdb4a3be93aa14.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-9c0374c7c783b34a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-ea3a0d48e5822b42.js +1 -0
- mage_ai/server/frontend_dist/block-layout.html +2 -2
- mage_ai/server/frontend_dist/files.html +2 -2
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
- mage_ai/server/frontend_dist/global-data-products.html +2 -2
- mage_ai/server/frontend_dist/index.html +2 -2
- mage_ai/server/frontend_dist/manage/settings.html +2 -2
- mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist/manage/users.html +2 -2
- mage_ai/server/frontend_dist/manage.html +2 -2
- mage_ai/server/frontend_dist/overview.html +2 -2
- mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist/pipelines.html +2 -2
- mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +24 -0
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +24 -0
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +24 -0
- mage_ai/server/frontend_dist/settings/workspace/roles.html +24 -0
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +24 -0
- mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist/settings.html +2 -2
- mage_ai/server/frontend_dist/sign-in.html +5 -5
- mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist/templates.html +2 -2
- mage_ai/server/frontend_dist/terminal.html +2 -2
- mage_ai/server/frontend_dist/test.html +2 -2
- mage_ai/server/frontend_dist/triggers.html +2 -2
- mage_ai/server/frontend_dist/version-control.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/L-IKw5_bRZUs-wyjnpN_j/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1124-d8fc76201b83b376.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1749-9ec0f4709f5a9284.js → 1749-a6bdce4ee8a09bce.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1769-613e23e361eb5bce.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1821-953efd0da290d25f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2327-1a797c758f8b064a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2677-a85c5a72bb695304.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/3419-6c8ec8db8c398c12.js → frontend_dist_base_path_template/_next/static/chunks/3419-0df6c5ef72f2e672.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3684-e1a713b7c16f0151.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/3859-3501cdba0a33f9f2.js → frontend_dist_base_path_template/_next/static/chunks/3859-ba594d21a1260cd2.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4636-84f545d1d238df13.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/4839-963da65cea58054f.js → frontend_dist_base_path_template/_next/static/chunks/4839-e5fe343a369734bc.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5457-97433bc45b42a88a.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/5499-63667ad5a785dba5.js → frontend_dist_base_path_template/_next/static/chunks/5499-b74459f6be5f9229.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6043-6ea109833b88eb1d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-ca4cd6a73a597a40.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7022-80d082a1d7fd1234.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7361-25f211ef377e5958.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/8013-1d6b1f7c13264cb4.js → frontend_dist_base_path_template/_next/static/chunks/8013-e67c71ddea072a20.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8146-941c5155c3bfcc35.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9161-837b653aa849a76f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-5730e4e059db40a8.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-752d991f239a128f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{block-layout-a624972d126a3dbd.js → block-layout-a27a28d2a615e364.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-98e27a4d7bd0da47.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/{[...slug]-a95787fe1695f493.js → [...slug]-9eb5dad57da13efd.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-data-products-0d55711df91a78d0.js → global-data-products-26909dec66f00231.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-b9eea6abc676ca81.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-11c601c6ef07fe86.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-ae6083077c9c1c41.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-bfce0ee677d57206.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-476c921d62f565fc.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/overview-9bc34ef66d84330a.js → frontend_dist_base_path_template/_next/static/chunks/pages/overview-2ec6b17e45a52be8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-605918f3a5c1aac4.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-84ec3ab0770bcd68.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ee65a62ed166bd85.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-2402004a19a6ad53.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-9a5b4768a640cd68.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-8781db69f19759a1.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-d7fd4857579e2b00.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-bd4bd009146bab36.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-234007c99efdccf6.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-8405a83adeaa8ff5.js → block-runs-da7510d4b277e47b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runtime-98aa0840a00cc661.js → block-runtime-eae853ff34b09481.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-0fb48e1cc51f78b2.js → monitors-a057b17847b82468.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/{[run]-845c1f010d5ec380.js → [run]-99d11c86f8b15369.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-9255f85760e1f57a.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-3f0980d8810a540b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{settings-187ac359020704e1.js → settings-9edf75d03460aaeb.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-c52d0c49439ec620.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-e7692e54979f037d.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-7b3b57523b226a0e.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-cb6a3bcaf4fa1a81.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-5eff96c149584e87.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{pipelines-efc080913a247e99.js → pipelines-270b912e1ac189b5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-2058d022972cdea4.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/[...slug]-1a95628ea8d0d846.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions-cb1cdf5f8e5bf9c5.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-58978256db4efbda.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/[...slug]-9ddd7eb842d5a911.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-1694c5eb1acbcf30.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-6850e854fbedbb61.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/[...slug]-5061c073e1c0de07.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-f551c5665bfd3494.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/sign-in-6fe3657070f98aca.js → frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-e779dbab123e626e.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/templates/[...slug]-935113d252ada806.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/templates-25b6d24cfa81c306.js → frontend_dist_base_path_template/_next/static/chunks/pages/templates-7079d637e396f2a8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/terminal-67fdb4a3be93aa14.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-9c0374c7c783b34a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-ea3a0d48e5822b42.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/files.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/overview.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +24 -0
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +24 -0
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +24 -0
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +24 -0
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +24 -0
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +13 -13
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/templates.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/terminal.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/test.html +4 -4
- mage_ai/server/frontend_dist_base_path_template/triggers.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/version-control.html +5 -5
- mage_ai/server/server.py +37 -2
- mage_ai/services/aws/__init__.py +19 -8
- mage_ai/services/spark/config.py +5 -1
- mage_ai/services/spark/spark.py +5 -4
- mage_ai/settings/__init__.py +2 -0
- mage_ai/streaming/constants.py +1 -0
- mage_ai/streaming/sinks/google_cloud_pubsub.py +66 -0
- mage_ai/streaming/sinks/sink_factory.py +6 -0
- mage_ai/tests/api/operations/test_operations.py +8 -2
- mage_ai/tests/api/operations/test_pipeline_schedules.py +3 -0
- mage_ai/tests/data_preparation/models/block/sql/utils/test_shared.py +130 -5
- mage_ai/tests/factory.py +2 -0
- mage_ai/tests/orchestration/test_pipeline_scheduler.py +20 -3
- mage_ai/tests/streaming/sinks/test_google_cloud_pubsub.py +28 -0
- mage_ai/usage_statistics/logger.py +4 -1
- {mage_ai-0.9.32.dist-info → mage_ai-0.9.34.dist-info}/METADATA +1 -1
- {mage_ai-0.9.32.dist-info → mage_ai-0.9.34.dist-info}/RECORD +302 -268
- mage_ai/api/policies/utils.py +0 -14
- mage_ai/server/frontend_dist/_next/static/cbN7L4Ms6UUPoANozEh9w/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1769-e2efd4df8d09481f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2327-2d8a1555605cf4af.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2369-cb9cd97052e18d27.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2677-aea54e655c4a727f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5457-994e1044953f1425.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5597-c034402ee26af3b4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6333-d1f8db4e7d9656a5.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6648-9bd31397f1d1b551.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9161-0101571a3635a938.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9264-7c4fcfed1200046a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9696-3e8ab7786f0e3a0e.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-976b488b8aea327f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-1a6c6654bfc953ac.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-49004d918b04c866.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/[user]-97177740fbb6eb9f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/new-5b6411c9eb8c4ba4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-0a7a746cc0998608.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-606012a580245001.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-0801de3c9a2976ea.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-0a5865d4cf012127.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-87b1a0601c4236cd.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-77ffaa2d721a0a4e.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-4e72d40881ac0605.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-8da8f8e2fdb1c99f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-be029347e99fcea2.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-d4b07df78b3d6037.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/[...slug]-87c492e9edc6064e.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/terminal-2ab9f3d0c50cce81.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-0ba40243a030ddf4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-28a3a43d65074394.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1769-e2efd4df8d09481f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2327-2d8a1555605cf4af.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2369-cb9cd97052e18d27.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2677-aea54e655c4a727f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5457-994e1044953f1425.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5597-c034402ee26af3b4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-d1f8db4e7d9656a5.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6648-9bd31397f1d1b551.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9161-0101571a3635a938.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-7c4fcfed1200046a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9696-3e8ab7786f0e3a0e.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-976b488b8aea327f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-1a6c6654bfc953ac.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-49004d918b04c866.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-97177740fbb6eb9f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-5b6411c9eb8c4ba4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-0a7a746cc0998608.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-606012a580245001.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-0801de3c9a2976ea.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-0a5865d4cf012127.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-87b1a0601c4236cd.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-77ffaa2d721a0a4e.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-4e72d40881ac0605.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-8da8f8e2fdb1c99f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-be029347e99fcea2.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-d4b07df78b3d6037.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/templates/[...slug]-87c492e9edc6064e.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/terminal-2ab9f3d0c50cce81.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-0ba40243a030ddf4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-28a3a43d65074394.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/o_Yc57jh8Te2SI-VoipGQ/_buildManifest.js +0 -1
- /mage_ai/server/frontend_dist/_next/static/{cbN7L4Ms6UUPoANozEh9w → PBVuphyo_muEAj347ZP_b}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{o_Yc57jh8Te2SI-VoipGQ → L-IKw5_bRZUs-wyjnpN_j}/_ssgManifest.js +0 -0
- {mage_ai-0.9.32.dist-info → mage_ai-0.9.34.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.32.dist-info → mage_ai-0.9.34.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.32.dist-info → mage_ai-0.9.34.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.32.dist-info → mage_ai-0.9.34.dist-info}/top_level.txt +0 -0
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import inspect
|
|
3
3
|
from collections.abc import Iterable
|
|
4
|
-
from typing import List, Tuple, Union
|
|
4
|
+
from typing import Callable, List, Tuple, Union
|
|
5
5
|
|
|
6
6
|
import inflection
|
|
7
7
|
|
|
8
8
|
from mage_ai import settings
|
|
9
9
|
from mage_ai.api.constants import AttributeOperationType, AttributeType
|
|
10
10
|
from mage_ai.api.errors import ApiError
|
|
11
|
+
from mage_ai.api.mixins.result_set import ResultSetMixIn
|
|
11
12
|
from mage_ai.api.oauth_scope import OauthScope
|
|
12
13
|
from mage_ai.api.operations.constants import OperationType
|
|
14
|
+
from mage_ai.api.policies.mixins.user_permissions import UserPermissionMixIn
|
|
15
|
+
from mage_ai.api.result_set import ResultSet
|
|
13
16
|
from mage_ai.api.utils import (
|
|
14
17
|
has_at_least_admin_role,
|
|
15
18
|
has_at_least_editor_role,
|
|
@@ -21,15 +24,23 @@ from mage_ai.api.utils import (
|
|
|
21
24
|
from mage_ai.data_preparation.repo_manager import get_project_uuid
|
|
22
25
|
from mage_ai.orchestration.constants import Entity
|
|
23
26
|
from mage_ai.services.tracking.metrics import increment
|
|
24
|
-
from mage_ai.settings import
|
|
27
|
+
from mage_ai.settings import (
|
|
28
|
+
DISABLE_NOTEBOOK_EDIT_ACCESS,
|
|
29
|
+
REQUIRE_USER_AUTHENTICATION,
|
|
30
|
+
REQUIRE_USER_PERMISSIONS,
|
|
31
|
+
)
|
|
25
32
|
from mage_ai.shared.hash import extract
|
|
26
33
|
|
|
27
34
|
|
|
28
|
-
class BasePolicy():
|
|
35
|
+
class BasePolicy(UserPermissionMixIn, ResultSetMixIn):
|
|
29
36
|
action_rules = {}
|
|
30
37
|
query_rules = {}
|
|
31
38
|
read_rules = {}
|
|
32
39
|
write_rules = {}
|
|
40
|
+
override_permission_action_rules = {}
|
|
41
|
+
override_permission_query_rules = {}
|
|
42
|
+
override_permission_read_rules = {}
|
|
43
|
+
override_permission_write_rules = {}
|
|
33
44
|
|
|
34
45
|
def __init__(self, resource, current_user, **kwargs):
|
|
35
46
|
self.current_user = current_user
|
|
@@ -37,10 +48,15 @@ class BasePolicy():
|
|
|
37
48
|
self.resource = resource
|
|
38
49
|
self.parent_model_attr = None
|
|
39
50
|
self.parent_resource_attr = None
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
self.result_set_attr = None
|
|
52
|
+
|
|
53
|
+
if resource:
|
|
54
|
+
if isinstance(resource, Iterable):
|
|
55
|
+
self.resources = resource
|
|
56
|
+
else:
|
|
57
|
+
self.resources = [resource]
|
|
42
58
|
else:
|
|
43
|
-
self.
|
|
59
|
+
self.result_set_attr = ResultSet([])
|
|
44
60
|
|
|
45
61
|
@property
|
|
46
62
|
def entity(self) -> Tuple[Union[Entity, None], Union[str, None]]:
|
|
@@ -48,60 +64,142 @@ class BasePolicy():
|
|
|
48
64
|
|
|
49
65
|
@classmethod
|
|
50
66
|
def action_rule(self, action):
|
|
67
|
+
if REQUIRE_USER_PERMISSIONS:
|
|
68
|
+
return self.action_rule_with_permissions(action)
|
|
69
|
+
|
|
51
70
|
if not self.action_rules.get(self.__name__):
|
|
52
71
|
self.action_rules[self.__name__] = {}
|
|
53
72
|
return self.action_rules[self.__name__].get(action)
|
|
54
73
|
|
|
74
|
+
@classmethod
|
|
75
|
+
def override_permission_action_rule(self, action):
|
|
76
|
+
if not self.override_permission_action_rules.get(self.__name__):
|
|
77
|
+
self.override_permission_action_rules[self.__name__] = {}
|
|
78
|
+
return self.override_permission_action_rules[self.__name__].get(action)
|
|
79
|
+
|
|
55
80
|
@classmethod
|
|
56
81
|
def query_rule(self, query):
|
|
82
|
+
if REQUIRE_USER_PERMISSIONS:
|
|
83
|
+
return self.attribute_rule_with_permissions(AttributeOperationType.QUERY, query)
|
|
84
|
+
|
|
57
85
|
if not self.query_rules.get(self.__name__):
|
|
58
86
|
self.query_rules[self.__name__] = {}
|
|
59
87
|
return self.query_rules[self.__name__].get(query)
|
|
60
88
|
|
|
89
|
+
@classmethod
|
|
90
|
+
def override_permission_query_rule(self, query):
|
|
91
|
+
if not self.override_permission_query_rules.get(self.__name__):
|
|
92
|
+
self.override_permission_query_rules[self.__name__] = {}
|
|
93
|
+
return self.override_permission_query_rules[self.__name__].get(query)
|
|
94
|
+
|
|
61
95
|
@classmethod
|
|
62
96
|
def read_rule(self, read):
|
|
97
|
+
if REQUIRE_USER_PERMISSIONS:
|
|
98
|
+
return self.attribute_rule_with_permissions(AttributeOperationType.READ, read)
|
|
99
|
+
|
|
63
100
|
if not self.read_rules.get(self.__name__):
|
|
64
101
|
self.read_rules[self.__name__] = {}
|
|
65
102
|
return self.read_rules[self.__name__].get(read)
|
|
66
103
|
|
|
104
|
+
@classmethod
|
|
105
|
+
def override_permission_read_rule(self, read):
|
|
106
|
+
if not self.override_permission_read_rules.get(self.__name__):
|
|
107
|
+
self.override_permission_read_rules[self.__name__] = {}
|
|
108
|
+
return self.override_permission_read_rules[self.__name__].get(read)
|
|
109
|
+
|
|
67
110
|
@classmethod
|
|
68
111
|
def write_rule(self, write):
|
|
112
|
+
if REQUIRE_USER_PERMISSIONS:
|
|
113
|
+
return self.attribute_rule_with_permissions(AttributeOperationType.WRITE, write)
|
|
114
|
+
|
|
69
115
|
if not self.write_rules.get(self.__name__):
|
|
70
116
|
self.write_rules[self.__name__] = {}
|
|
71
117
|
return self.write_rules[self.__name__].get(write)
|
|
72
118
|
|
|
119
|
+
@classmethod
|
|
120
|
+
def override_permission_write_rule(self, write):
|
|
121
|
+
if not self.override_permission_write_rules.get(self.__name__):
|
|
122
|
+
self.override_permission_write_rules[self.__name__] = {}
|
|
123
|
+
return self.override_permission_write_rules[self.__name__].get(write)
|
|
124
|
+
|
|
73
125
|
@classmethod
|
|
74
126
|
def allow_actions(self, array, **kwargs):
|
|
75
127
|
if not self.action_rules.get(self.__name__):
|
|
76
128
|
self.action_rules[self.__name__] = {}
|
|
77
|
-
|
|
129
|
+
if not self.override_permission_action_rules.get(self.__name__):
|
|
130
|
+
self.override_permission_action_rules[self.__name__] = {}
|
|
131
|
+
|
|
132
|
+
array_use = array or [OperationType.ALL]
|
|
133
|
+
for key in array_use:
|
|
78
134
|
if not self.action_rules[self.__name__].get(key):
|
|
79
135
|
self.action_rules[self.__name__][key] = {}
|
|
80
136
|
for scope in kwargs.get('scopes', []):
|
|
81
137
|
self.action_rules[self.__name__][key][scope] = extract(kwargs, [
|
|
82
138
|
'condition'])
|
|
139
|
+
if not self.override_permission_action_rules[self.__name__].get(key):
|
|
140
|
+
self.override_permission_action_rules[self.__name__][key] = {}
|
|
141
|
+
for scope in kwargs.get('scopes', []):
|
|
142
|
+
self.override_permission_action_rules[self.__name__][key][scope] = extract(
|
|
143
|
+
kwargs,
|
|
144
|
+
[
|
|
145
|
+
'override_permission_condition',
|
|
146
|
+
],
|
|
147
|
+
)
|
|
83
148
|
|
|
84
149
|
@classmethod
|
|
85
150
|
def allow_query(self, array: List = None, **kwargs):
|
|
86
151
|
if not self.query_rules.get(self.__name__):
|
|
87
152
|
self.query_rules[self.__name__] = {}
|
|
153
|
+
if not self.override_permission_query_rules.get(self.__name__):
|
|
154
|
+
self.override_permission_query_rules[self.__name__] = {}
|
|
88
155
|
|
|
89
156
|
array_use = array or [AttributeType.ALL]
|
|
90
157
|
for key in array_use:
|
|
91
158
|
if not self.query_rules[self.__name__].get(key):
|
|
92
159
|
self.query_rules[self.__name__][key] = {}
|
|
160
|
+
if not self.override_permission_query_rules[self.__name__].get(key):
|
|
161
|
+
self.override_permission_query_rules[self.__name__][key] = {}
|
|
162
|
+
|
|
163
|
+
actions = kwargs.get('on_action', [OperationType.ALL])
|
|
164
|
+
actions = actions if isinstance(actions, list) else [actions]
|
|
165
|
+
|
|
93
166
|
for scope in kwargs.get('scopes', []):
|
|
94
|
-
self.query_rules[self.__name__][key]
|
|
167
|
+
if not self.query_rules[self.__name__][key].get(scope):
|
|
168
|
+
self.query_rules[self.__name__][key][scope] = {}
|
|
169
|
+
for action in actions:
|
|
170
|
+
self.query_rules[self.__name__][key][scope][action] = extract(
|
|
171
|
+
kwargs,
|
|
172
|
+
[
|
|
173
|
+
'condition',
|
|
174
|
+
],
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if not self.override_permission_query_rules[self.__name__][key].get(scope):
|
|
178
|
+
self.override_permission_query_rules[self.__name__][key][scope] = {}
|
|
179
|
+
for action in actions:
|
|
180
|
+
self.override_permission_query_rules[self.__name__][key][scope][action] = \
|
|
181
|
+
extract(
|
|
182
|
+
kwargs,
|
|
183
|
+
[
|
|
184
|
+
'override_permission_condition',
|
|
185
|
+
])
|
|
95
186
|
|
|
96
187
|
@classmethod
|
|
97
188
|
def allow_read(self, array, **kwargs):
|
|
98
189
|
if not self.read_rules.get(self.__name__):
|
|
99
190
|
self.read_rules[self.__name__] = {}
|
|
191
|
+
if not self.override_permission_read_rules.get(self.__name__):
|
|
192
|
+
self.override_permission_read_rules[self.__name__] = {}
|
|
193
|
+
|
|
100
194
|
for key in array:
|
|
101
195
|
if not self.read_rules[self.__name__].get(key):
|
|
102
196
|
self.read_rules[self.__name__][key] = {}
|
|
197
|
+
if not self.override_permission_read_rules[self.__name__].get(key):
|
|
198
|
+
self.override_permission_read_rules[self.__name__][key] = {}
|
|
199
|
+
|
|
103
200
|
actions = kwargs.get('on_action', [OperationType.ALL])
|
|
104
201
|
actions = actions if isinstance(actions, list) else [actions]
|
|
202
|
+
|
|
105
203
|
for scope in kwargs.get('scopes', []):
|
|
106
204
|
if not self.read_rules[self.__name__][key].get(scope):
|
|
107
205
|
self.read_rules[self.__name__][key][scope] = {}
|
|
@@ -109,15 +207,32 @@ class BasePolicy():
|
|
|
109
207
|
self.read_rules[self.__name__][key][scope][action] = extract(kwargs, [
|
|
110
208
|
'condition'])
|
|
111
209
|
|
|
210
|
+
if not self.override_permission_read_rules[self.__name__][key].get(scope):
|
|
211
|
+
self.override_permission_read_rules[self.__name__][key][scope] = {}
|
|
212
|
+
for action in actions:
|
|
213
|
+
self.override_permission_read_rules[self.__name__][key][scope][action] = \
|
|
214
|
+
extract(
|
|
215
|
+
kwargs,
|
|
216
|
+
[
|
|
217
|
+
'override_permission_condition',
|
|
218
|
+
])
|
|
219
|
+
|
|
112
220
|
@classmethod
|
|
113
221
|
def allow_write(self, array, **kwargs):
|
|
114
222
|
if not self.write_rules.get(self.__name__):
|
|
115
223
|
self.write_rules[self.__name__] = {}
|
|
224
|
+
if not self.override_permission_write_rules.get(self.__name__):
|
|
225
|
+
self.override_permission_write_rules[self.__name__] = {}
|
|
226
|
+
|
|
116
227
|
for key in array:
|
|
117
228
|
if not self.write_rules[self.__name__].get(key):
|
|
118
229
|
self.write_rules[self.__name__][key] = {}
|
|
230
|
+
if not self.override_permission_write_rules[self.__name__].get(key):
|
|
231
|
+
self.override_permission_write_rules[self.__name__][key] = {}
|
|
232
|
+
|
|
119
233
|
actions = kwargs.get('on_action', [OperationType.ALL])
|
|
120
234
|
actions = actions if isinstance(actions, list) else [actions]
|
|
235
|
+
|
|
121
236
|
for scope in kwargs.get('scopes', []):
|
|
122
237
|
if not self.write_rules[self.__name__][key].get(scope):
|
|
123
238
|
self.write_rules[self.__name__][key][scope] = {}
|
|
@@ -125,10 +240,24 @@ class BasePolicy():
|
|
|
125
240
|
self.write_rules[self.__name__][key][scope][action] = extract(kwargs, [
|
|
126
241
|
'condition'])
|
|
127
242
|
|
|
243
|
+
if not self.override_permission_write_rules[self.__name__][key].get(scope):
|
|
244
|
+
self.override_permission_write_rules[self.__name__][key][scope] = {}
|
|
245
|
+
for action in actions:
|
|
246
|
+
self.override_permission_write_rules[self.__name__][key][scope][action] = \
|
|
247
|
+
extract(
|
|
248
|
+
kwargs,
|
|
249
|
+
[
|
|
250
|
+
'override_permission_condition',
|
|
251
|
+
])
|
|
252
|
+
|
|
128
253
|
@classmethod
|
|
129
254
|
def resource_name(self):
|
|
130
255
|
return inflection.pluralize(self.resource_name_singular())
|
|
131
256
|
|
|
257
|
+
@classmethod
|
|
258
|
+
def model_name(self) -> str:
|
|
259
|
+
return self.__name__.replace('Policy', '')
|
|
260
|
+
|
|
132
261
|
@classmethod
|
|
133
262
|
def resource_name_singular(self):
|
|
134
263
|
return inflection.underscore(
|
|
@@ -178,6 +307,9 @@ class BasePolicy():
|
|
|
178
307
|
)
|
|
179
308
|
|
|
180
309
|
async def authorize_action(self, action):
|
|
310
|
+
if self.is_owner():
|
|
311
|
+
return True
|
|
312
|
+
|
|
181
313
|
config = self.__class__.action_rule(action)
|
|
182
314
|
if config:
|
|
183
315
|
await self.__validate_scopes(action, config.keys())
|
|
@@ -187,6 +319,9 @@ class BasePolicy():
|
|
|
187
319
|
action,
|
|
188
320
|
config[self.current_scope()]['condition'],
|
|
189
321
|
operation=action,
|
|
322
|
+
override_permission_condition=(self.__class__.override_permission_action_rule(
|
|
323
|
+
action,
|
|
324
|
+
) or {}).get(self.current_scope(), {}).get('override_permission_condition'),
|
|
190
325
|
)
|
|
191
326
|
else:
|
|
192
327
|
error = ApiError.UNAUTHORIZED_ACCESS
|
|
@@ -207,9 +342,11 @@ class BasePolicy():
|
|
|
207
342
|
if 'read' == read_or_write:
|
|
208
343
|
attribute_operation = AttributeOperationType.READ
|
|
209
344
|
orig_config = self.__class__.read_rule(attrb)
|
|
345
|
+
orig_config_override = self.__class__.override_permission_read_rule(attrb)
|
|
210
346
|
else:
|
|
211
|
-
orig_config = self.__class__.write_rule(attrb)
|
|
212
347
|
attribute_operation = AttributeOperationType.WRITE
|
|
348
|
+
orig_config = self.__class__.write_rule(attrb)
|
|
349
|
+
orig_config_override = self.__class__.override_permission_write_rule(attrb)
|
|
213
350
|
|
|
214
351
|
config = None
|
|
215
352
|
if orig_config:
|
|
@@ -220,6 +357,15 @@ class BasePolicy():
|
|
|
220
357
|
if config is None:
|
|
221
358
|
config = config_scope.get(OperationType.ALL)
|
|
222
359
|
|
|
360
|
+
config_override = None
|
|
361
|
+
if orig_config_override:
|
|
362
|
+
await self.__validate_scopes(attrb, orig_config_override.keys())
|
|
363
|
+
config_override_scope = orig_config_override.get(self.current_scope(), {})
|
|
364
|
+
config_override = config_override_scope.get(api_operation_action)
|
|
365
|
+
|
|
366
|
+
if config_override is None:
|
|
367
|
+
config_override = config_override_scope.get(OperationType.ALL)
|
|
368
|
+
|
|
223
369
|
if config is None:
|
|
224
370
|
error = ApiError.UNAUTHORIZED_ACCESS
|
|
225
371
|
error.update({
|
|
@@ -231,13 +377,16 @@ class BasePolicy():
|
|
|
231
377
|
),
|
|
232
378
|
})
|
|
233
379
|
raise ApiError(error)
|
|
380
|
+
|
|
234
381
|
cond = config.get('condition')
|
|
382
|
+
|
|
235
383
|
if cond:
|
|
236
384
|
await self.__validate_condition(
|
|
237
385
|
attrb,
|
|
238
386
|
cond,
|
|
239
387
|
attribute_operation=attribute_operation,
|
|
240
388
|
operation=api_operation_action,
|
|
389
|
+
override_permission_condition=config_override.get('override_permission_condition'),
|
|
241
390
|
**kwargs,
|
|
242
391
|
)
|
|
243
392
|
|
|
@@ -248,36 +397,63 @@ class BasePolicy():
|
|
|
248
397
|
for attrb in attrbs:
|
|
249
398
|
await self.authorize_attribute(read_or_write, attrb, **kwargs)
|
|
250
399
|
|
|
251
|
-
async def authorize_query(self, query):
|
|
252
|
-
if not query:
|
|
253
|
-
return
|
|
400
|
+
async def authorize_query(self, query, **kwargs):
|
|
401
|
+
if self.is_owner() or not query:
|
|
402
|
+
return True
|
|
403
|
+
|
|
404
|
+
api_operation_action = self.options.get(
|
|
405
|
+
'api_operation_action',
|
|
406
|
+
kwargs.get('api_operation_action', OperationType.ALL),
|
|
407
|
+
)
|
|
254
408
|
|
|
255
409
|
for key, value in query.items():
|
|
256
|
-
if key
|
|
257
|
-
|
|
258
|
-
'api_operation_action',
|
|
259
|
-
OperationType.ALL,
|
|
260
|
-
)
|
|
410
|
+
if key == settings.QUERY_API_KEY:
|
|
411
|
+
continue
|
|
261
412
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
413
|
+
error_message = f'Query parameter {key} of value {value} ' \
|
|
414
|
+
f'is not permitted on {api_operation_action} operation ' \
|
|
415
|
+
f'for {self.__class__.resource_name()}.'
|
|
416
|
+
|
|
417
|
+
orig_config = self.__class__.query_rule(key) or \
|
|
418
|
+
self.__class__.query_rule(AttributeType.ALL)
|
|
419
|
+
|
|
420
|
+
config = None
|
|
421
|
+
if orig_config:
|
|
422
|
+
await self.__validate_scopes(key, orig_config.keys())
|
|
423
|
+
config_scope = orig_config.get(self.current_scope(), {})
|
|
424
|
+
config = config_scope.get(api_operation_action)
|
|
425
|
+
|
|
426
|
+
if config is None:
|
|
427
|
+
config = config_scope.get(OperationType.ALL)
|
|
428
|
+
|
|
429
|
+
orig_config_override = self.__class__.override_permission_query_rule(key) or \
|
|
430
|
+
self.__class__.override_permission_query_rule(AttributeType.ALL)
|
|
431
|
+
|
|
432
|
+
config_override = None
|
|
433
|
+
if orig_config_override:
|
|
434
|
+
await self.__validate_scopes(key, orig_config_override.keys())
|
|
435
|
+
config_override_scope = orig_config_override.get(self.current_scope(), {})
|
|
436
|
+
config_override = config_override_scope.get(api_operation_action)
|
|
437
|
+
|
|
438
|
+
if config_override is None:
|
|
439
|
+
config_override = config_override_scope.get(OperationType.ALL)
|
|
440
|
+
|
|
441
|
+
if config is None:
|
|
442
|
+
error = ApiError.UNAUTHORIZED_ACCESS
|
|
443
|
+
error.update({
|
|
444
|
+
'message': error_message,
|
|
445
|
+
})
|
|
446
|
+
raise ApiError(error)
|
|
447
|
+
|
|
448
|
+
cond = config.get('condition')
|
|
449
|
+
|
|
450
|
+
await self.__validate_condition(
|
|
451
|
+
key,
|
|
452
|
+
cond,
|
|
453
|
+
message=error_message,
|
|
454
|
+
operation=api_operation_action,
|
|
455
|
+
override_permission_condition=config_override.get('override_permission_condition'),
|
|
456
|
+
)
|
|
281
457
|
|
|
282
458
|
def parent_model(self):
|
|
283
459
|
if not self.parent_model_attr:
|
|
@@ -306,12 +482,19 @@ class BasePolicy():
|
|
|
306
482
|
else:
|
|
307
483
|
return OauthScope.CLIENT_PUBLIC
|
|
308
484
|
|
|
485
|
+
def result_set(self) -> ResultSet:
|
|
486
|
+
if self.resource:
|
|
487
|
+
return self.resource.result_set()
|
|
488
|
+
|
|
489
|
+
return self.result_set_attr
|
|
490
|
+
|
|
309
491
|
async def __validate_condition(
|
|
310
492
|
self,
|
|
311
493
|
action,
|
|
312
494
|
cond,
|
|
313
495
|
attribute_operation: AttributeOperationType = None,
|
|
314
496
|
operation: OperationType = None,
|
|
497
|
+
override_permission_condition: Callable = None,
|
|
315
498
|
**kwargs,
|
|
316
499
|
):
|
|
317
500
|
if not cond:
|
|
@@ -321,16 +504,22 @@ class BasePolicy():
|
|
|
321
504
|
if validation and inspect.isawaitable(validation):
|
|
322
505
|
validation = await validation
|
|
323
506
|
|
|
507
|
+
if not validation and override_permission_condition:
|
|
508
|
+
validation = override_permission_condition(self)
|
|
509
|
+
if validation and inspect.isawaitable(validation):
|
|
510
|
+
validation = await validation
|
|
511
|
+
|
|
324
512
|
if not validation:
|
|
513
|
+
r_name = self.resource_name()
|
|
325
514
|
error = ApiError.UNAUTHORIZED_ACCESS
|
|
326
|
-
message = f'Unauthorized access for {action}'
|
|
515
|
+
message = f'Unauthorized access for {action} on {r_name}'
|
|
327
516
|
|
|
328
517
|
if attribute_operation:
|
|
329
|
-
message = f'Unauthorized {attribute_operation} access for {action}'
|
|
518
|
+
message = f'Unauthorized {attribute_operation} access for {action} on {r_name}'
|
|
330
519
|
if operation:
|
|
331
|
-
message = f'{message}
|
|
520
|
+
message = f'{message} for {operation} operation'
|
|
332
521
|
elif operation:
|
|
333
|
-
message = f'Unauthorized
|
|
522
|
+
message = f'Unauthorized operation {operation} on {r_name}'
|
|
334
523
|
|
|
335
524
|
error.update({
|
|
336
525
|
'message': kwargs.get(
|
|
@@ -26,6 +26,8 @@ PermissionPolicy.allow_actions([
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
PermissionPolicy.allow_read(PermissionPresenter.default_attributes + [
|
|
29
|
+
'entity_names',
|
|
30
|
+
'entity_types',
|
|
29
31
|
'query_attributes',
|
|
30
32
|
'read_attributes',
|
|
31
33
|
'write_attributes',
|
|
@@ -41,11 +43,16 @@ PermissionPolicy.allow_read(PermissionPresenter.default_attributes + [
|
|
|
41
43
|
|
|
42
44
|
PermissionPolicy.allow_read(PermissionPresenter.default_attributes + [
|
|
43
45
|
'role',
|
|
46
|
+
'user',
|
|
44
47
|
'user_id',
|
|
48
|
+
'users',
|
|
45
49
|
], scopes=[
|
|
46
50
|
OauthScope.CLIENT_PRIVATE,
|
|
47
51
|
], on_action=[
|
|
52
|
+
constants.CREATE,
|
|
53
|
+
constants.DELETE,
|
|
48
54
|
constants.DETAIL,
|
|
55
|
+
constants.UPDATE,
|
|
49
56
|
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
50
57
|
|
|
51
58
|
|
|
@@ -56,9 +63,19 @@ PermissionPolicy.allow_write([
|
|
|
56
63
|
'entity_name',
|
|
57
64
|
'entity_type',
|
|
58
65
|
'role_id',
|
|
66
|
+
'role_ids',
|
|
59
67
|
], scopes=[
|
|
60
68
|
OauthScope.CLIENT_PRIVATE,
|
|
61
69
|
], on_action=[
|
|
62
70
|
constants.CREATE,
|
|
63
71
|
constants.UPDATE,
|
|
64
72
|
], condition=lambda policy: policy.has_at_least_admin_role())
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
PermissionPolicy.allow_query([
|
|
76
|
+
'only_entity_options',
|
|
77
|
+
], scopes=[
|
|
78
|
+
OauthScope.CLIENT_PRIVATE,
|
|
79
|
+
], on_action=[
|
|
80
|
+
constants.LIST,
|
|
81
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from mage_ai.api.oauth_scope import OauthScope
|
|
2
2
|
from mage_ai.api.operations import constants
|
|
3
3
|
from mage_ai.api.policies.BasePolicy import BasePolicy
|
|
4
|
-
from mage_ai.api.policies.utils import validate_pipeline_interactions_permissions
|
|
5
4
|
from mage_ai.api.presenters.PipelineSchedulePresenter import PipelineSchedulePresenter
|
|
5
|
+
from mage_ai.data_preparation.models.pipelines.interactions import PipelineInteractions
|
|
6
|
+
from mage_ai.data_preparation.models.project import Project
|
|
7
|
+
from mage_ai.data_preparation.models.project.constants import FeatureUUID
|
|
6
8
|
from mage_ai.data_preparation.repo_manager import get_project_uuid
|
|
7
9
|
from mage_ai.orchestration.constants import Entity
|
|
8
10
|
|
|
@@ -40,7 +42,21 @@ async def authorize_operation_create(policy: PipelineSchedulePolicy) -> bool:
|
|
|
40
42
|
if policy.has_at_least_editor_role():
|
|
41
43
|
return True
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
pipeline = policy.parent_model()
|
|
46
|
+
if not pipeline:
|
|
47
|
+
pipeline = policy.resource.pipeline
|
|
48
|
+
|
|
49
|
+
if not Project(pipeline.repo_config).is_feature_enabled(FeatureUUID.INTERACTIONS):
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
pipeline_interaction = PipelineInteractions(pipeline)
|
|
53
|
+
cond = await pipeline_interaction.filter_for_permissions(policy.current_user)
|
|
54
|
+
|
|
55
|
+
if not policy.result_set().context.data:
|
|
56
|
+
policy.result_set().context.data = {}
|
|
57
|
+
if not policy.result_set().context.data.get('pipeline_interactions'):
|
|
58
|
+
policy.result_set().context.data['pipeline_interactions'] = {}
|
|
59
|
+
policy.result_set().context.data['pipeline_interactions'][pipeline.uuid] = pipeline_interaction
|
|
44
60
|
|
|
45
61
|
return cond
|
|
46
62
|
|
|
@@ -44,6 +44,7 @@ RolePolicy.allow_read([
|
|
|
44
44
|
|
|
45
45
|
RolePolicy.allow_read(RolePresenter.default_attributes + [
|
|
46
46
|
'user_id',
|
|
47
|
+
'users',
|
|
47
48
|
], scopes=[
|
|
48
49
|
OauthScope.CLIENT_PRIVATE,
|
|
49
50
|
], on_action=[
|
|
@@ -55,6 +56,8 @@ RolePolicy.allow_read(RolePresenter.default_attributes + [
|
|
|
55
56
|
|
|
56
57
|
RolePolicy.allow_write([
|
|
57
58
|
'name'
|
|
59
|
+
'permission_ids',
|
|
60
|
+
'user_ids',
|
|
58
61
|
], scopes=[
|
|
59
62
|
OauthScope.CLIENT_PRIVATE,
|
|
60
63
|
], on_action=[
|
|
@@ -1,10 +1,45 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from mage_ai.api.constants import AttributeOperationType
|
|
1
4
|
from mage_ai.api.oauth_scope import OauthScope
|
|
2
5
|
from mage_ai.api.operations import constants
|
|
6
|
+
from mage_ai.api.operations.constants import OperationType
|
|
3
7
|
from mage_ai.api.policies.BasePolicy import BasePolicy
|
|
8
|
+
from mage_ai.api.policies.mixins.user_permissions import UserPermissionMixIn
|
|
4
9
|
from mage_ai.orchestration.constants import Entity
|
|
10
|
+
from mage_ai.shared.hash import merge_dict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SessionPolicy(BasePolicy, UserPermissionMixIn):
|
|
14
|
+
@classmethod
|
|
15
|
+
def action_rule_with_permissions(self, operation: OperationType) -> Dict:
|
|
16
|
+
return merge_dict(super().action_rule_with_permissions(operation), {
|
|
17
|
+
OauthScope.CLIENT_PUBLIC: dict(
|
|
18
|
+
condition=lambda _policy: OperationType.CREATE == operation,
|
|
19
|
+
),
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def attribute_rule_with_permissions(
|
|
24
|
+
self,
|
|
25
|
+
attribute_operation_type: AttributeOperationType,
|
|
26
|
+
resource_attribute: str,
|
|
27
|
+
) -> Dict:
|
|
28
|
+
config = {}
|
|
29
|
+
if AttributeOperationType.READ == attribute_operation_type:
|
|
30
|
+
config = self.read_rules[self.__name__].get(resource_attribute)
|
|
31
|
+
else:
|
|
32
|
+
config = self.write_rules[self.__name__].get(resource_attribute)
|
|
5
33
|
|
|
34
|
+
return merge_dict(super().attribute_rule_with_permissions(
|
|
35
|
+
attribute_operation_type,
|
|
36
|
+
resource_attribute,
|
|
37
|
+
), {
|
|
38
|
+
OauthScope.CLIENT_PUBLIC: {
|
|
39
|
+
OperationType.CREATE: config[OauthScope.CLIENT_PUBLIC][OperationType.CREATE],
|
|
40
|
+
},
|
|
41
|
+
})
|
|
6
42
|
|
|
7
|
-
class SessionPolicy(BasePolicy):
|
|
8
43
|
@property
|
|
9
44
|
def entity(self):
|
|
10
45
|
return Entity.ANY, None
|