diff --git a/api/migrations/versions/2025_07_04_1705-71f5020c6470_tool_oauth.py b/api/migrations/versions/2025_07_04_1705-71f5020c6470_tool_oauth.py index 0dbbdb4650..ad73563246 100644 --- a/api/migrations/versions/2025_07_04_1705-71f5020c6470_tool_oauth.py +++ b/api/migrations/versions/2025_07_04_1705-71f5020c6470_tool_oauth.py @@ -37,29 +37,26 @@ def upgrade(): sa.PrimaryKeyConstraint('id', name='tool_oauth_tenant_client_pkey'), sa.UniqueConstraint('tenant_id', 'plugin_id', 'provider', name='unique_tool_oauth_tenant_client') ) - with op.batch_alter_table('tool_api_providers', schema=None) as batch_op: - batch_op.drop_constraint(batch_op.f('unique_api_tool_provider'), type_='unique') with op.batch_alter_table('tool_builtin_providers', schema=None) as batch_op: batch_op.add_column(sa.Column('name', sa.String(length=256), server_default=sa.text("'API KEY 1'::character varying"), nullable=False)) batch_op.add_column(sa.Column('is_default', sa.Boolean(), server_default=sa.text('false'), nullable=False)) batch_op.add_column(sa.Column('credential_type', sa.String(length=32), server_default=sa.text("'api-key'::character varying"), nullable=False)) batch_op.drop_constraint(batch_op.f('unique_builtin_tool_provider'), type_='unique') - + batch_op.create_unique_constraint(batch_op.f('unique_builtin_tool_provider'), ['tenant_id', 'provider', 'name']) + # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### with op.batch_alter_table('tool_builtin_providers', schema=None) as batch_op: + batch_op.drop_constraint(batch_op.f('unique_builtin_tool_provider'), type_='unique') batch_op.create_unique_constraint(batch_op.f('unique_builtin_tool_provider'), ['tenant_id', 'provider']) batch_op.drop_column('credential_type') batch_op.drop_column('is_default') batch_op.drop_column('name') - with op.batch_alter_table('tool_api_providers', schema=None) as batch_op: - batch_op.create_unique_constraint(batch_op.f('unique_api_tool_provider'), ['name', 'tenant_id']) - op.drop_table('tool_oauth_tenant_clients') op.drop_table('tool_oauth_system_clients') # ### end Alembic commands ### diff --git a/api/models/tools.py b/api/models/tools.py index 74c6ed4b3e..34bc97d006 100644 --- a/api/models/tools.py +++ b/api/models/tools.py @@ -109,7 +109,10 @@ class ApiToolProvider(Base): """ __tablename__ = "tool_api_providers" - __table_args__ = (db.PrimaryKeyConstraint("id", name="tool_api_provider_pkey"),) + __table_args__ = ( + db.PrimaryKeyConstraint("id", name="tool_api_provider_pkey"), + db.UniqueConstraint("name", "tenant_id", name="unique_api_tool_provider"), + ) id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()")) # name of the api provider diff --git a/api/services/tools/builtin_tools_manage_service.py b/api/services/tools/builtin_tools_manage_service.py index fea74ba492..66157fb6b6 100644 --- a/api/services/tools/builtin_tools_manage_service.py +++ b/api/services/tools/builtin_tools_manage_service.py @@ -43,12 +43,22 @@ class BuiltinToolManageService: get builtin tool provider oauth client schema """ provider = ToolManager.get_builtin_provider(provider_name, tenant_id) - return { + + is_oauth_custom_client_enabled = BuiltinToolManageService.is_oauth_custom_client_enabled( + tenant_id, provider_name + ) + is_system_oauth_params_exists = BuiltinToolManageService.is_oauth_system_client_exists(provider_name) + result = { "schema": provider.get_oauth_client_schema(), - "is_oauth_custom_client_enabled": BuiltinToolManageService.is_oauth_custom_client_enabled( - tenant_id, provider_name - ), + "is_oauth_custom_client_enabled": is_oauth_custom_client_enabled, + "is_system_oauth_params_exists": is_system_oauth_params_exists, } + if is_oauth_custom_client_enabled: + result["client_params"] = BuiltinToolManageService.get_oauth_client(tenant_id, provider_name) + result["redirect_uri"] = ( + f"{dify_config.CONSOLE_API_URL}/console/api/oauth/plugin/{provider_name}/tool/callback" + ) + return result @staticmethod def list_builtin_tool_provider_tools(tenant_id: str, provider: str) -> list[ToolApiEntity]: @@ -415,6 +425,20 @@ class BuiltinToolManageService: session.commit() return {"result": "success"} + @staticmethod + def is_oauth_system_client_exists(provider_name: str) -> bool: + """ + check if oauth system client exists + """ + tool_provider = ToolProviderID(provider_name) + with Session(db.engine).no_autoflush as session: + system_client: ToolOAuthSystemClient | None = ( + session.query(ToolOAuthSystemClient) + .filter_by(plugin_id=tool_provider.plugin_id, provider=tool_provider.provider_name) + .first() + ) + return system_client is not None + @staticmethod def is_oauth_custom_client_enabled(tenant_id: str, provider: str) -> bool: """ @@ -685,4 +709,10 @@ class BuiltinToolManageService: config=[x.to_basic_provider_config() for x in provider_controller.get_oauth_client_schema()], cache=NoOpProviderCredentialCache(), ) - return encrypter.mask_tool_credentials(encrypter.decrypt(custom_oauth_client_params.oauth_params)) + + return { + "oauth_params": encrypter.mask_tool_credentials( + encrypter.decrypt(custom_oauth_client_params.oauth_params) + ), + "enabled": custom_oauth_client_params.enabled, + } diff --git a/api/services/tools/mcp_tools_mange_service.py b/api/services/tools/mcp_tools_mange_service.py index 3d3ecdcced..fda6da5983 100644 --- a/api/services/tools/mcp_tools_mange_service.py +++ b/api/services/tools/mcp_tools_mange_service.py @@ -70,6 +70,7 @@ class MCPToolManageService: MCPToolProvider.server_url_hash == server_url_hash, MCPToolProvider.server_identifier == server_identifier, ), + MCPToolProvider.tenant_id == tenant_id, ) .first() )