From affd07ae9421a816dc7753d00c06068a1657a882 Mon Sep 17 00:00:00 2001 From: L1nSn0w Date: Thu, 12 Feb 2026 15:45:24 +0800 Subject: [PATCH 1/2] fix: make e-1.12.1 enterprise migrations database-agnostic for MySQL/TiDB (#32267) Co-authored-by: Cursor --- .../2025_12_25_1039-7df29de0f6be_add_credit_pool.py | 3 +-- ...9f6d18a37f9_add_table_explore_banner_and_trial.py | 11 +++++------ api/models/model.py | 12 ++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/api/migrations/versions/2025_12_25_1039-7df29de0f6be_add_credit_pool.py b/api/migrations/versions/2025_12_25_1039-7df29de0f6be_add_credit_pool.py index e89fcee7e5..0d42de6a3a 100644 --- a/api/migrations/versions/2025_12_25_1039-7df29de0f6be_add_credit_pool.py +++ b/api/migrations/versions/2025_12_25_1039-7df29de0f6be_add_credit_pool.py @@ -8,7 +8,6 @@ Create Date: 2025-12-25 10:39:15.139304 from alembic import op import models as models import sqlalchemy as sa -from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = '7df29de0f6be' @@ -20,7 +19,7 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table('tenant_credit_pools', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('id', models.types.StringUUID(), nullable=False), sa.Column('tenant_id', models.types.StringUUID(), nullable=False), sa.Column('pool_type', sa.String(length=40), server_default='trial', nullable=False), sa.Column('quota_limit', sa.BigInteger(), nullable=False), diff --git a/api/migrations/versions/2026_01_17_1110-f9f6d18a37f9_add_table_explore_banner_and_trial.py b/api/migrations/versions/2026_01_17_1110-f9f6d18a37f9_add_table_explore_banner_and_trial.py index b99ca04e3f..52672e8db6 100644 --- a/api/migrations/versions/2026_01_17_1110-f9f6d18a37f9_add_table_explore_banner_and_trial.py +++ b/api/migrations/versions/2026_01_17_1110-f9f6d18a37f9_add_table_explore_banner_and_trial.py @@ -8,7 +8,6 @@ Create Date: 2026-01-017 11:10:18.079355 from alembic import op import models as models import sqlalchemy as sa -from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = 'f9f6d18a37f9' @@ -20,7 +19,7 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table('account_trial_app_records', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('id', models.types.StringUUID(), nullable=False), sa.Column('account_id', models.types.StringUUID(), nullable=False), sa.Column('app_id', models.types.StringUUID(), nullable=False), sa.Column('count', sa.Integer(), nullable=False), @@ -33,17 +32,17 @@ def upgrade(): batch_op.create_index('account_trial_app_record_app_id_idx', ['app_id'], unique=False) op.create_table('exporle_banners', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('id', models.types.StringUUID(), nullable=False), sa.Column('content', sa.JSON(), nullable=False), sa.Column('link', sa.String(length=255), nullable=False), sa.Column('sort', sa.Integer(), nullable=False), - sa.Column('status', sa.String(length=255), server_default=sa.text("'enabled'::character varying"), nullable=False), + sa.Column('status', sa.String(length=255), server_default='enabled', nullable=False), sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('language', sa.String(length=255), server_default=sa.text("'en-US'::character varying"), nullable=False), + sa.Column('language', sa.String(length=255), server_default='en-US', nullable=False), sa.PrimaryKeyConstraint('id', name='exporler_banner_pkey') ) op.create_table('trial_apps', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('id', models.types.StringUUID(), nullable=False), sa.Column('app_id', models.types.StringUUID(), nullable=False), sa.Column('tenant_id', models.types.StringUUID(), nullable=False), sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), diff --git a/api/models/model.py b/api/models/model.py index c1c6e04ce9..429c46bd85 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -620,7 +620,7 @@ class TrialApp(Base): sa.UniqueConstraint("app_id", name="unique_trail_app_id"), ) - id = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()")) + id = mapped_column(StringUUID, default=lambda: str(uuid4())) app_id = mapped_column(StringUUID, nullable=False) tenant_id = mapped_column(StringUUID, nullable=False) created_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @@ -640,7 +640,7 @@ class AccountTrialAppRecord(Base): sa.Index("account_trial_app_record_app_id_idx", "app_id"), sa.UniqueConstraint("account_id", "app_id", name="unique_account_trial_app_record"), ) - id = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()")) + id = mapped_column(StringUUID, default=lambda: str(uuid4())) account_id = mapped_column(StringUUID, nullable=False) app_id = mapped_column(StringUUID, nullable=False) count = mapped_column(sa.Integer, nullable=False, default=0) @@ -660,18 +660,18 @@ class AccountTrialAppRecord(Base): class ExporleBanner(TypeBase): __tablename__ = "exporle_banners" __table_args__ = (sa.PrimaryKeyConstraint("id", name="exporler_banner_pkey"),) - id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()"), init=False) + id: Mapped[str] = mapped_column(StringUUID, default=lambda: str(uuid4()), init=False) content: Mapped[dict[str, Any]] = mapped_column(sa.JSON, nullable=False) link: Mapped[str] = mapped_column(String(255), nullable=False) sort: Mapped[int] = mapped_column(sa.Integer, nullable=False) status: Mapped[str] = mapped_column( - sa.String(255), nullable=False, server_default=sa.text("'enabled'::character varying"), default="enabled" + sa.String(255), nullable=False, server_default='enabled', default="enabled" ) created_at: Mapped[datetime] = mapped_column( sa.DateTime, nullable=False, server_default=func.current_timestamp(), init=False ) language: Mapped[str] = mapped_column( - String(255), nullable=False, server_default=sa.text("'en-US'::character varying"), default="en-US" + String(255), nullable=False, server_default='en-US', default="en-US" ) @@ -2166,7 +2166,7 @@ class TenantCreditPool(TypeBase): sa.Index("tenant_credit_pool_pool_type_idx", "pool_type"), ) - id: Mapped[str] = mapped_column(StringUUID, primary_key=True, server_default=text("uuid_generate_v4()"), init=False) + id: Mapped[str] = mapped_column(StringUUID, primary_key=True, default=lambda: str(uuid4()), init=False) tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False) pool_type: Mapped[str] = mapped_column(String(40), nullable=False, default="trial", server_default="trial") quota_limit: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0) From efbdb4c7065ac836b30fe82e2d3da713026704e6 Mon Sep 17 00:00:00 2001 From: GareArc Date: Fri, 13 Feb 2026 22:08:50 -0800 Subject: [PATCH 2/2] fix(app-copy): inherit web app permission from original app When copying an app, the copied app was not getting a web_app_settings record created. This caused the enterprise service to query for settings that don't exist, falling back to default behavior. This fix ensures copied apps inherit the same access mode as the original: - If original has explicit settings (public/private/private_all/sso_verified), the copy gets the same setting - If original has no settings (old apps), copy defaults to 'public' to match the original's effective permission via fallback This prevents permission mismatches between original and copied apps and ensures the enterprise service has explicit settings to query. Related: langgenius/dify-enterprise#423 --- api/controllers/console/app/app.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/api/controllers/console/app/app.py b/api/controllers/console/app/app.py index 91034f2d87..42901ab590 100644 --- a/api/controllers/console/app/app.py +++ b/api/controllers/console/app/app.py @@ -660,6 +660,19 @@ class AppCopyApi(Resource): ) session.commit() + # Inherit web app permission from original app + if result.app_id and FeatureService.get_system_features().webapp_auth.enabled: + try: + # Get the original app's access mode + original_settings = EnterpriseService.WebAppAuth.get_app_access_mode_by_id(app_model.id) + access_mode = original_settings.access_mode + except Exception: + # If original app has no settings (old app), default to public to match fallback behavior + access_mode = "public" + + # Apply the same access mode to the copied app + EnterpriseService.WebAppAuth.update_app_access_mode(result.app_id, access_mode) + stmt = select(App).where(App.id == result.app_id) app = session.scalar(stmt)