mage-ai 0.9.65__py3-none-any.whl → 0.9.67__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/monitors/BaseMonitor.py +38 -16
- mage_ai/api/policies/BackfillPolicy.py +1 -0
- mage_ai/api/resources/OauthResource.py +13 -5
- mage_ai/api/resources/SessionResource.py +6 -4
- mage_ai/authentication/ldap.py +19 -9
- mage_ai/authentication/oauth/constants.py +8 -14
- mage_ai/authentication/oauth/utils.py +18 -6
- mage_ai/authentication/providers/active_directory.py +21 -16
- mage_ai/authentication/providers/azure_devops.py +18 -0
- mage_ai/authentication/providers/bitbucket.py +10 -9
- mage_ai/authentication/providers/constants.py +2 -0
- mage_ai/authentication/providers/ghe.py +5 -9
- mage_ai/authentication/providers/gitlab.py +6 -9
- mage_ai/authentication/providers/google.py +9 -6
- mage_ai/authentication/providers/oidc.py +6 -4
- mage_ai/authentication/providers/okta.py +9 -6
- mage_ai/cluster_manager/kubernetes/workload_manager.py +10 -0
- mage_ai/cluster_manager/workspace/base.py +6 -1
- mage_ai/cluster_manager/workspace/kubernetes.py +3 -0
- mage_ai/data_preparation/decorators.py +15 -0
- mage_ai/data_preparation/executors/streaming_pipeline_executor.py +22 -12
- mage_ai/data_preparation/git/__init__.py +10 -1
- mage_ai/data_preparation/git/api.py +3 -0
- mage_ai/data_preparation/git/clients/azure_devops.py +106 -0
- mage_ai/data_preparation/git/clients/base.py +6 -0
- mage_ai/data_preparation/git/clients/gitlab.py +3 -2
- mage_ai/data_preparation/git/utils.py +31 -29
- mage_ai/data_preparation/models/block/__init__.py +27 -18
- mage_ai/data_preparation/models/block/dbt/block_sql.py +164 -0
- mage_ai/data_preparation/models/block/dynamic/variables.py +1 -2
- mage_ai/data_preparation/models/pipeline.py +3 -3
- mage_ai/data_preparation/models/triggers/__init__.py +6 -1
- mage_ai/data_preparation/preferences.py +42 -37
- mage_ai/data_preparation/repo_manager.py +21 -0
- mage_ai/data_preparation/storage/gcs_storage.py +27 -2
- mage_ai/data_preparation/storage/local_storage.py +18 -3
- mage_ai/data_preparation/storage/s3_storage.py +7 -2
- mage_ai/data_preparation/templates/data_loaders/streaming/generic_python.py +23 -0
- mage_ai/data_preparation/templates/main/metadata.yaml +6 -0
- mage_ai/data_preparation/templates/template.py +6 -2
- mage_ai/data_preparation/variable_manager.py +2 -1
- mage_ai/io/base.py +3 -0
- mage_ai/io/bigquery.py +2 -0
- mage_ai/io/export_utils.py +14 -9
- mage_ai/io/mssql.py +104 -25
- mage_ai/io/mysql.py +10 -9
- mage_ai/io/oracledb.py +14 -2
- mage_ai/io/postgres.py +3 -0
- mage_ai/io/sql.py +14 -6
- mage_ai/io/trino.py +10 -8
- mage_ai/orchestration/db/migrations/versions/90d978a8aef8_update_unique_constraint_for_secret.py +11 -5
- mage_ai/orchestration/db/models/schedules.py +25 -1
- mage_ai/orchestration/db/models/schedules_project_platform.py +24 -1
- mage_ai/orchestration/job_manager.py +6 -1
- mage_ai/orchestration/pipeline_scheduler_original.py +16 -10
- mage_ai/server/constants.py +1 -1
- mage_ai/server/file_observer.py +10 -0
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/_next/static/chunks/{1557-a754b04510d50b80.js → 1557-01f0843dc6ac4971.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9440-4069842b90d4b801.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-1c1ffd928f5a00f7.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/index-b7b8695a7f9efde2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/oauth-30e34ee15d410331.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-aaf393c86fc1bda3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{edit-8d32ac7e8f023779.js → edit-36377e679da2cd91.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-3f5c14076ddde20e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-fe08120d9a6fb1b0.js → triggers-f508c2f261297724.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-bcdb4ad41dd4c7d5.js → frontend_dist/_next/static/chunks/pages/pipelines-f99e99aa8f45529c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{sign-in-19b36600d908b711.js → sign-in-7d38b2f7c3e918a1.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{webpack-ac7fdc472bedf682.js → webpack-d079359c241db804.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/{ZMrJfDouIX5AMb_RteRbL → vPsMu6Fi2zrHaf2fRXKRO}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist/block-layout.html +2 -2
- mage_ai/server/frontend_dist/compute.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/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist/global-hooks.html +2 -2
- mage_ai/server/frontend_dist/index.html +2 -2
- mage_ai/server/frontend_dist/manage/files.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/oauth.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/platform/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist/platform/global-hooks.html +2 -2
- mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist/settings/platform/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/platform/settings.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +2 -2
- 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 +2 -2
- 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/chunks/{1557-a754b04510d50b80.js → 1557-01f0843dc6ac4971.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-4069842b90d4b801.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-1c1ffd928f5a00f7.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-b7b8695a7f9efde2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/oauth-30e34ee15d410331.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-aaf393c86fc1bda3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{edit-8d32ac7e8f023779.js → edit-36377e679da2cd91.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-3f5c14076ddde20e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-fe08120d9a6fb1b0.js → triggers-f508c2f261297724.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines-bcdb4ad41dd4c7d5.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-f99e99aa8f45529c.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{sign-in-19b36600d908b711.js → sign-in-7d38b2f7c3e918a1.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-481689d9989710cd.js → webpack-68c003fb6a175cd7.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/{QYwFH4sievaq5XyUjRriy → khKiaJtwrslgMmp4YSa1f}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/compute.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/oauth.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +2 -2
- 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 +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/test.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
- mage_ai/server/server.py +117 -87
- mage_ai/server/utils/output_display.py +6 -1
- mage_ai/services/aws/s3/s3.py +8 -2
- mage_ai/services/slack/slack.py +8 -8
- mage_ai/settings/__init__.py +36 -186
- mage_ai/settings/backends.py +95 -0
- mage_ai/settings/keys/__init__.py +1 -0
- mage_ai/settings/keys/auth.py +76 -0
- mage_ai/settings/server.py +187 -0
- mage_ai/shared/io.py +2 -2
- mage_ai/shared/logger.py +12 -6
- mage_ai/streaming/sources/base_python.py +30 -0
- mage_ai/streaming/sources/source_factory.py +25 -0
- mage_ai/tests/api/endpoints/test_oauths.py +13 -5
- mage_ai/tests/api/operations/test_operations.py +2 -2
- mage_ai/tests/api/operations/test_sessions.py +83 -48
- mage_ai/tests/authentication/oauth/test_utils.py +56 -6
- mage_ai/tests/authentication/providers/test_active_directory.py +9 -15
- mage_ai/tests/data_preparation/models/test_block.py +39 -2
- mage_ai/tests/orchestration/db/models/test_schedules.py +33 -1
- {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/METADATA +2 -1
- {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/RECORD +225 -217
- {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/WHEEL +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9440-2bcbdc765ed82062.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-2ae1d919333f01fe.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/index-64851458dde54ad9.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/oauth-abe5ba687cb93509.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-22e49726eeed16ae.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c74507dce89b41a2.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-cf656cbe37ecaacc.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-690206d30d8b412b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-2bcbdc765ed82062.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-2ae1d919333f01fe.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-64851458dde54ad9.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/oauth-abe5ba687cb93509.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-22e49726eeed16ae.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c74507dce89b41a2.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-cf656cbe37ecaacc.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-690206d30d8b412b.js +0 -1
- mage_ai/settings/sso.py +0 -27
- /mage_ai/server/frontend_dist/_next/static/{ZMrJfDouIX5AMb_RteRbL → vPsMu6Fi2zrHaf2fRXKRO}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{QYwFH4sievaq5XyUjRriy → khKiaJtwrslgMmp4YSa1f}/_ssgManifest.js +0 -0
- {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
from unittest.mock import patch
|
|
4
5
|
|
|
@@ -20,15 +21,20 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
20
21
|
|
|
21
22
|
operation = self.build_operation(
|
|
22
23
|
action=constants.CREATE,
|
|
23
|
-
payload=dict(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
payload=dict(
|
|
25
|
+
session=dict(
|
|
26
|
+
email=user.email,
|
|
27
|
+
password=password,
|
|
28
|
+
)
|
|
29
|
+
),
|
|
27
30
|
resource='sessions',
|
|
31
|
+
user=None,
|
|
28
32
|
)
|
|
29
33
|
response = await operation.execute()
|
|
30
34
|
|
|
31
|
-
access_token = Oauth2AccessToken.query.filter(
|
|
35
|
+
access_token = Oauth2AccessToken.query.filter(
|
|
36
|
+
Oauth2AccessToken.user_id == user.id
|
|
37
|
+
).first()
|
|
32
38
|
|
|
33
39
|
self.assertEqual(
|
|
34
40
|
response['session']['token'],
|
|
@@ -41,22 +47,32 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
41
47
|
user = create_user(password=password)
|
|
42
48
|
|
|
43
49
|
with patch('mage_ai.api.policies.BasePolicy.DISABLE_NOTEBOOK_EDIT_ACCESS', 1):
|
|
44
|
-
with patch(
|
|
45
|
-
|
|
50
|
+
with patch(
|
|
51
|
+
'mage_ai.api.policies.BasePolicy.REQUIRE_USER_AUTHENTICATION', 1
|
|
52
|
+
):
|
|
53
|
+
with patch(
|
|
54
|
+
'mage_ai.api.policies.BasePolicy.REQUIRE_USER_PERMISSIONS', 0
|
|
55
|
+
):
|
|
46
56
|
operation = self.build_operation(
|
|
47
57
|
action=constants.CREATE,
|
|
48
|
-
payload=dict(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
payload=dict(
|
|
59
|
+
session=dict(
|
|
60
|
+
email=user.email,
|
|
61
|
+
password=password,
|
|
62
|
+
)
|
|
63
|
+
),
|
|
52
64
|
resource='sessions',
|
|
53
65
|
user=None,
|
|
54
66
|
)
|
|
55
67
|
response = await operation.execute()
|
|
56
68
|
|
|
57
|
-
access_token =
|
|
58
|
-
Oauth2AccessToken.
|
|
59
|
-
|
|
69
|
+
access_token = (
|
|
70
|
+
Oauth2AccessToken.query.filter(
|
|
71
|
+
Oauth2AccessToken.user_id == user.id
|
|
72
|
+
)
|
|
73
|
+
.order_by(Oauth2AccessToken.created_at.desc())
|
|
74
|
+
.first()
|
|
75
|
+
)
|
|
60
76
|
|
|
61
77
|
self.assertEqual(
|
|
62
78
|
response['session']['token'],
|
|
@@ -69,11 +85,14 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
69
85
|
|
|
70
86
|
operation = self.build_operation(
|
|
71
87
|
action=constants.CREATE,
|
|
72
|
-
payload=dict(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
payload=dict(
|
|
89
|
+
session=dict(
|
|
90
|
+
email=user.email,
|
|
91
|
+
password='not password',
|
|
92
|
+
)
|
|
93
|
+
),
|
|
76
94
|
resource='sessions',
|
|
95
|
+
user=None,
|
|
77
96
|
)
|
|
78
97
|
response = await operation.execute()
|
|
79
98
|
|
|
@@ -89,11 +108,14 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
89
108
|
username = "novachrono"
|
|
90
109
|
operation = self.build_operation(
|
|
91
110
|
action=constants.CREATE,
|
|
92
|
-
payload=dict(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
111
|
+
payload=dict(
|
|
112
|
+
session=dict(
|
|
113
|
+
email=username,
|
|
114
|
+
password="Wizard King",
|
|
115
|
+
)
|
|
116
|
+
),
|
|
96
117
|
resource='sessions',
|
|
118
|
+
user=None,
|
|
97
119
|
)
|
|
98
120
|
await operation.execute()
|
|
99
121
|
|
|
@@ -111,11 +133,14 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
111
133
|
username = "licht"
|
|
112
134
|
operation = self.build_operation(
|
|
113
135
|
action=constants.CREATE,
|
|
114
|
-
payload=dict(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
136
|
+
payload=dict(
|
|
137
|
+
session=dict(
|
|
138
|
+
email=username,
|
|
139
|
+
password="Golden Dawn",
|
|
140
|
+
)
|
|
141
|
+
),
|
|
118
142
|
resource='sessions',
|
|
143
|
+
user=None,
|
|
119
144
|
)
|
|
120
145
|
response = await operation.execute()
|
|
121
146
|
|
|
@@ -134,11 +159,14 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
134
159
|
username = "yami"
|
|
135
160
|
operation = self.build_operation(
|
|
136
161
|
action=constants.CREATE,
|
|
137
|
-
payload=dict(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
162
|
+
payload=dict(
|
|
163
|
+
session=dict(
|
|
164
|
+
email=username,
|
|
165
|
+
password="black bull",
|
|
166
|
+
)
|
|
167
|
+
),
|
|
141
168
|
resource='sessions',
|
|
169
|
+
user=None,
|
|
142
170
|
)
|
|
143
171
|
response = await operation.execute()
|
|
144
172
|
|
|
@@ -148,28 +176,35 @@ class SessionOperationTests(BaseApiTestCase):
|
|
|
148
176
|
self.assertIsNotNone(response['error'])
|
|
149
177
|
|
|
150
178
|
@patch('mage_ai.api.resources.SessionResource.AUTHENTICATION_MODE', 'ldap')
|
|
151
|
-
@patch('mage_ai.authentication.ldap.LDAP_ROLES_MAPPING', json.dumps(dict(Admin=['Admin'])))
|
|
152
179
|
@patch.object(LDAPConnection, 'authorize')
|
|
153
180
|
@patch.object(LDAPConnection, 'authenticate')
|
|
154
181
|
async def test_ldap_login_with_role_mapping(self, mock_authenticate, mock_authorize):
|
|
155
|
-
mock_authenticate.return_value = (
|
|
182
|
+
mock_authenticate.return_value = (
|
|
183
|
+
True,
|
|
184
|
+
"Yami_Sukehiro",
|
|
185
|
+
dict(memberOf=['Admin']),
|
|
186
|
+
)
|
|
156
187
|
mock_authorize.return_value = True
|
|
157
188
|
|
|
158
189
|
Role.create_default_roles()
|
|
159
190
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
with patch.dict(os.environ, dict(LDAP_ROLES_MAPPING=json.dumps(dict(Admin=['Admin'])))):
|
|
192
|
+
username = self.faker.email()
|
|
193
|
+
operation = self.build_operation(
|
|
194
|
+
action=constants.CREATE,
|
|
195
|
+
payload=dict(
|
|
196
|
+
session=dict(
|
|
197
|
+
email=username,
|
|
198
|
+
password="black bull",
|
|
199
|
+
)
|
|
200
|
+
),
|
|
201
|
+
resource='sessions',
|
|
202
|
+
user=None,
|
|
203
|
+
)
|
|
204
|
+
await operation.execute()
|
|
205
|
+
|
|
206
|
+
mock_authenticate.assert_called_once_with(username, "black bull")
|
|
207
|
+
mock_authorize.assert_called_once_with("Yami_Sukehiro")
|
|
208
|
+
user = User.query.filter(User.username == username).first()
|
|
209
|
+
self.assertIsNotNone(user)
|
|
210
|
+
self.assertEqual(user.roles_new[0].name, 'Admin')
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from datetime import datetime, timedelta
|
|
3
3
|
from unittest.mock import MagicMock, patch
|
|
4
|
+
from uuid import uuid4
|
|
4
5
|
|
|
5
6
|
from freezegun import freeze_time
|
|
6
7
|
|
|
7
8
|
from mage_ai.authentication.oauth.constants import ProviderName
|
|
8
|
-
from mage_ai.authentication.oauth.utils import
|
|
9
|
+
from mage_ai.authentication.oauth.utils import (
|
|
10
|
+
access_tokens_for_client,
|
|
11
|
+
refresh_token_for_client,
|
|
12
|
+
)
|
|
9
13
|
from mage_ai.data_preparation.git.api import get_oauth_client_id
|
|
10
14
|
from mage_ai.orchestration.db.models.oauth import Oauth2AccessToken, Oauth2Application
|
|
11
15
|
from mage_ai.tests.base_test import AsyncDBTestCase
|
|
16
|
+
from mage_ai.tests.factory import create_user
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
class OauthUtilsTest(AsyncDBTestCase):
|
|
@@ -17,11 +22,54 @@ class OauthUtilsTest(AsyncDBTestCase):
|
|
|
17
22
|
super().setUpClass()
|
|
18
23
|
self.provider = ProviderName.GITLAB
|
|
19
24
|
self.client_id = get_oauth_client_id(self.provider)
|
|
25
|
+
|
|
26
|
+
def setUp(self):
|
|
20
27
|
self.oauth_application = Oauth2Application.create(
|
|
21
28
|
client_id=self.client_id,
|
|
22
29
|
client_type=Oauth2Application.ClientType.PRIVATE,
|
|
23
30
|
name=self.provider,
|
|
24
31
|
)
|
|
32
|
+
self.user = create_user()
|
|
33
|
+
|
|
34
|
+
def tearDown(self):
|
|
35
|
+
Oauth2Application.query.delete()
|
|
36
|
+
Oauth2AccessToken.query.delete()
|
|
37
|
+
|
|
38
|
+
super().tearDown()
|
|
39
|
+
|
|
40
|
+
def test_access_tokens_for_client(self):
|
|
41
|
+
token = Oauth2AccessToken.create(
|
|
42
|
+
expires=datetime.utcnow() + timedelta(days=1),
|
|
43
|
+
token=uuid4().hex,
|
|
44
|
+
oauth2_application_id=self.oauth_application.id,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
tokens = access_tokens_for_client(self.client_id)
|
|
48
|
+
|
|
49
|
+
self.assertEqual(len(tokens), 1)
|
|
50
|
+
self.assertEqual(tokens[0].token, token.token)
|
|
51
|
+
|
|
52
|
+
def test_access_tokens_for_client_with_user(self):
|
|
53
|
+
Oauth2AccessToken.create(
|
|
54
|
+
expires=datetime.utcnow() + timedelta(days=1),
|
|
55
|
+
token=uuid4().hex,
|
|
56
|
+
oauth2_application_id=self.oauth_application.id,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
self.assertEqual(
|
|
60
|
+
len(access_tokens_for_client(self.client_id, user=self.user)), 0
|
|
61
|
+
)
|
|
62
|
+
self.assertEqual(len(access_tokens_for_client(self.client_id)), 1)
|
|
63
|
+
|
|
64
|
+
token = Oauth2AccessToken.create(
|
|
65
|
+
expires=datetime.utcnow() + timedelta(days=1),
|
|
66
|
+
token=uuid4().hex,
|
|
67
|
+
oauth2_application_id=self.oauth_application.id,
|
|
68
|
+
user_id=self.user.id,
|
|
69
|
+
)
|
|
70
|
+
tokens = access_tokens_for_client(self.client_id, user=self.user)
|
|
71
|
+
self.assertEqual(len(tokens), 1)
|
|
72
|
+
self.assertEqual(tokens[0].token, token.token)
|
|
25
73
|
|
|
26
74
|
@freeze_time('2024-02-06 04:00:00')
|
|
27
75
|
@patch(
|
|
@@ -43,11 +91,13 @@ class OauthUtilsTest(AsyncDBTestCase):
|
|
|
43
91
|
provider_instance.provider = self.provider
|
|
44
92
|
|
|
45
93
|
future = asyncio.Future()
|
|
46
|
-
future.set_result(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
94
|
+
future.set_result(
|
|
95
|
+
{
|
|
96
|
+
'access_token': 'new',
|
|
97
|
+
'refresh_token': 'new_refresh',
|
|
98
|
+
'expires_in': 3600,
|
|
99
|
+
}
|
|
100
|
+
)
|
|
51
101
|
provider_instance.get_refresh_token_response.return_value = future
|
|
52
102
|
new_token = await refresh_token_for_client(self.client_id, provider_instance)
|
|
53
103
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import unittest
|
|
3
4
|
from unittest.mock import AsyncMock, Mock, patch
|
|
4
5
|
|
|
@@ -6,18 +7,6 @@ from mage_ai.authentication.providers.active_directory import ADProvider
|
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class ADProviderTest(unittest.IsolatedAsyncioTestCase):
|
|
9
|
-
@patch(
|
|
10
|
-
'mage_ai.authentication.providers.active_directory.ACTIVE_DIRECTORY_DIRECTORY_ID',
|
|
11
|
-
'test_directory_id',
|
|
12
|
-
)
|
|
13
|
-
@patch(
|
|
14
|
-
'mage_ai.authentication.providers.active_directory.ACTIVE_DIRECTORY_CLIENT_ID',
|
|
15
|
-
'test_client_id',
|
|
16
|
-
)
|
|
17
|
-
@patch(
|
|
18
|
-
'mage_ai.authentication.providers.active_directory.ACTIVE_DIRECTORY_CLIENT_SECRET',
|
|
19
|
-
'test_client_secret',
|
|
20
|
-
)
|
|
21
10
|
@patch('aiohttp.ClientSession')
|
|
22
11
|
async def test_map_ad_roles_to_mage_roles(self, mock_client_session):
|
|
23
12
|
roles_mapping = json.dumps(
|
|
@@ -27,9 +16,14 @@ class ADProviderTest(unittest.IsolatedAsyncioTestCase):
|
|
|
27
16
|
}
|
|
28
17
|
)
|
|
29
18
|
|
|
30
|
-
with patch(
|
|
31
|
-
|
|
32
|
-
|
|
19
|
+
with patch.dict(
|
|
20
|
+
os.environ,
|
|
21
|
+
dict(
|
|
22
|
+
ACTIVE_DIRECTORY_DIRECTORY_ID='test_directory_id',
|
|
23
|
+
ACTIVE_DIRECTORY_CLIENT_ID='test_client_id',
|
|
24
|
+
ACTIVE_DIRECTORY_CLIENT_SECRET='test_client_secret',
|
|
25
|
+
ACTIVE_DIRECTORY_ROLES_MAPPING=roles_mapping,
|
|
26
|
+
),
|
|
33
27
|
):
|
|
34
28
|
|
|
35
29
|
def side_effect(*args, **kwargs):
|
|
@@ -7,14 +7,17 @@ from faker import Faker
|
|
|
7
7
|
from pandas.testing import assert_frame_equal
|
|
8
8
|
|
|
9
9
|
# from mage_ai.data_cleaner.column_types.constants import ColumnType
|
|
10
|
-
from mage_ai.data_preparation.models.block import Block, BlockType
|
|
10
|
+
from mage_ai.data_preparation.models.block import Block, BlockType, CallbackBlock
|
|
11
11
|
from mage_ai.data_preparation.models.block.errors import HasDownstreamDependencies
|
|
12
12
|
from mage_ai.data_preparation.models.pipeline import Pipeline
|
|
13
13
|
from mage_ai.data_preparation.repo_manager import get_repo_config
|
|
14
14
|
from mage_ai.data_preparation.variable_manager import VariableManager
|
|
15
15
|
from mage_ai.shared.path_fixer import add_root_repo_path_to_relative_path
|
|
16
16
|
from mage_ai.tests.base_test import DBTestCase
|
|
17
|
-
from mage_ai.tests.factory import
|
|
17
|
+
from mage_ai.tests.factory import (
|
|
18
|
+
create_integration_pipeline_with_blocks,
|
|
19
|
+
create_pipeline,
|
|
20
|
+
)
|
|
18
21
|
from mage_ai.tests.shared.mixins import ProjectPlatformMixin
|
|
19
22
|
|
|
20
23
|
|
|
@@ -763,3 +766,37 @@ class BlockProjectPlatformTests(ProjectPlatformMixin):
|
|
|
763
766
|
)
|
|
764
767
|
|
|
765
768
|
self.assertEqual(block.file_path, add_root_repo_path_to_relative_path(path))
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
class CallbackBlockTest(DBTestCase):
|
|
772
|
+
def setUp(self):
|
|
773
|
+
self.pipeline = create_pipeline('callback_pipeline', self.repo_path)
|
|
774
|
+
|
|
775
|
+
def tearDown(self):
|
|
776
|
+
self.pipeline.delete()
|
|
777
|
+
|
|
778
|
+
def test_create_global_vars_from_parent_block(self):
|
|
779
|
+
parent_block = Block.create(
|
|
780
|
+
'test_data_loader',
|
|
781
|
+
'data_loader',
|
|
782
|
+
self.repo_path,
|
|
783
|
+
pipeline=self.pipeline,
|
|
784
|
+
)
|
|
785
|
+
callback_block = CallbackBlock.create(parent_block.name)
|
|
786
|
+
self.pipeline.add_block(callback_block)
|
|
787
|
+
parent_block = parent_block.update(
|
|
788
|
+
dict(callback_blocks=[callback_block.uuid])
|
|
789
|
+
)
|
|
790
|
+
parent_block.global_vars = dict(
|
|
791
|
+
configuration=dict(table_name='load_data_table')
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
global_vars = dict(
|
|
795
|
+
random_var=1,
|
|
796
|
+
)
|
|
797
|
+
new_vars = callback_block._create_global_vars(
|
|
798
|
+
global_vars,
|
|
799
|
+
parent_block=parent_block,
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
self.assertIsNotNone(new_vars.get('configuration'))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from datetime import datetime, timezone
|
|
2
|
+
from datetime import datetime, timedelta, timezone
|
|
3
3
|
from unittest.mock import Mock, patch
|
|
4
4
|
from uuid import uuid4
|
|
5
5
|
|
|
@@ -1677,6 +1677,38 @@ class PipelineRunTests(DBTestCase):
|
|
|
1677
1677
|
set([pipeline_run2.id, pipeline_run4.id]),
|
|
1678
1678
|
)
|
|
1679
1679
|
|
|
1680
|
+
@freeze_time('2023-10-11 12:13:14')
|
|
1681
|
+
def test_get_variables_intervals_for_cron(self):
|
|
1682
|
+
pipeline_schedule = PipelineSchedule.create(
|
|
1683
|
+
name=self.faker.unique.name(),
|
|
1684
|
+
pipeline_uuid=self.pipeline.uuid,
|
|
1685
|
+
schedule_interval='*/10 * * * *',
|
|
1686
|
+
schedule_type=ScheduleType.TIME,
|
|
1687
|
+
)
|
|
1688
|
+
|
|
1689
|
+
pipeline_run = PipelineRun.create(
|
|
1690
|
+
pipeline_uuid=self.pipeline.uuid,
|
|
1691
|
+
pipeline_schedule_id=pipeline_schedule.id,
|
|
1692
|
+
create_block_runs=False,
|
|
1693
|
+
execution_date=pipeline_schedule.current_execution_date(),
|
|
1694
|
+
)
|
|
1695
|
+
|
|
1696
|
+
variables = pipeline_run.get_variables(pipeline_uuid=pipeline_run.pipeline_uuid)
|
|
1697
|
+
|
|
1698
|
+
self.assertEqual(
|
|
1699
|
+
datetime(2023, 10, 11, 12, 20, 0) - variables['interval_end_datetime'],
|
|
1700
|
+
timedelta(0),
|
|
1701
|
+
)
|
|
1702
|
+
self.assertEqual(600, variables['interval_seconds'])
|
|
1703
|
+
self.assertEqual(
|
|
1704
|
+
datetime(2023, 10, 11, 12, 10, 0) - variables['interval_start_datetime'],
|
|
1705
|
+
timedelta(0),
|
|
1706
|
+
)
|
|
1707
|
+
self.assertEqual(
|
|
1708
|
+
datetime(2023, 10, 11, 12, 0, 0) - variables['interval_start_datetime_previous'],
|
|
1709
|
+
timedelta(0),
|
|
1710
|
+
)
|
|
1711
|
+
|
|
1680
1712
|
|
|
1681
1713
|
class BlockRunTests(DBTestCase):
|
|
1682
1714
|
@classmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mage-ai
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.67
|
|
4
4
|
Summary: Mage is a tool for building and deploying data pipelines.
|
|
5
5
|
Home-page: https://github.com/mage-ai/mage-ai
|
|
6
6
|
Author: Mage
|
|
@@ -58,6 +58,7 @@ Requires-Dist: thefuzz[speedup] ==0.19.0
|
|
|
58
58
|
Requires-Dist: tornado ==6.3.3
|
|
59
59
|
Requires-Dist: typer[all] ==0.9.0
|
|
60
60
|
Requires-Dist: typing-extensions ==4.5.0
|
|
61
|
+
Requires-Dist: watchdog ==4.0.0
|
|
61
62
|
Provides-Extra: ai
|
|
62
63
|
Requires-Dist: astor >=0.8.1 ; extra == 'ai'
|
|
63
64
|
Requires-Dist: langchain >=0.0.222 ; extra == 'ai'
|