mirror of
https://github.com/langgenius/dify.git
synced 2026-09-24 23:22:26 +08:00
refactor(api): migrate workspace tool endpoints to BaseModel (#37959)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,19 @@
|
||||
import logging
|
||||
from typing import Any, Literal
|
||||
from typing import Any
|
||||
|
||||
from flask import make_response, redirect, request
|
||||
from flask_restx import Resource
|
||||
from pydantic import BaseModel, Field, RootModel, model_validator
|
||||
from pydantic import BaseModel, RootModel, model_validator
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from werkzeug.exceptions import BadRequest, Forbidden
|
||||
|
||||
from configs import dify_config
|
||||
from controllers.common.errors import NotFoundError
|
||||
from controllers.common.fields import BinaryFileResponse, RedirectResponse, SimpleResultResponse
|
||||
from controllers.common.fields import SimpleResultResponse
|
||||
from controllers.common.schema import register_response_schema_models, register_schema_models
|
||||
from core.entities.parameter_entities import AppSelectorScope, ModelSelectorScope, ToolSelectorScope
|
||||
from core.entities.provider_entities import ProviderConfig
|
||||
from core.plugin.entities.plugin_daemon import CredentialType
|
||||
from core.plugin.impl.oauth import OAuthHandler
|
||||
from core.tools.entities.common_entities import I18nObject
|
||||
from core.trigger.entities.api_entities import (
|
||||
SubscriptionBuilderApiEntity,
|
||||
TriggerProviderApiEntity,
|
||||
@@ -24,7 +23,7 @@ from core.trigger.entities.entities import RequestLog, SubscriptionBuilderUpdate
|
||||
from core.trigger.trigger_manager import TriggerManager
|
||||
from extensions.ext_database import db
|
||||
from fields.base import ResponseModel
|
||||
from graphon.model_runtime.utils.encoders import jsonable_encoder
|
||||
from libs.helper import dump_response
|
||||
from libs.login import login_required
|
||||
from models.account import Account
|
||||
from models.provider_ids import TriggerProviderID
|
||||
@@ -59,9 +58,9 @@ class TriggerSubscriptionBuilderVerifyPayload(BaseModel):
|
||||
|
||||
class TriggerSubscriptionBuilderUpdatePayload(BaseModel):
|
||||
name: str | None = None
|
||||
parameters: dict[str, Any] | None = Field(default=None)
|
||||
properties: dict[str, Any] | None = Field(default=None)
|
||||
credentials: dict[str, Any] | None = Field(default=None)
|
||||
parameters: dict[str, Any] | None = None
|
||||
properties: dict[str, Any] | None = None
|
||||
credentials: dict[str, Any] | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def check_at_least_one_field(self):
|
||||
@@ -71,70 +70,23 @@ class TriggerSubscriptionBuilderUpdatePayload(BaseModel):
|
||||
|
||||
|
||||
class TriggerOAuthClientPayload(BaseModel):
|
||||
client_params: dict[str, Any] | None = Field(default=None)
|
||||
client_params: dict[str, Any] | None = None
|
||||
enabled: bool | None = None
|
||||
|
||||
|
||||
class TriggerOAuthAuthorizeResponse(BaseModel):
|
||||
authorization_url: str
|
||||
subscription_builder_id: str
|
||||
subscription_builder: SubscriptionBuilderApiEntity
|
||||
|
||||
|
||||
class TriggerProviderConfigOptionResponse(BaseModel):
|
||||
value: str = Field(..., description="The value of the option")
|
||||
label: I18nObject = Field(..., description="The label of the option")
|
||||
|
||||
|
||||
class TriggerProviderConfigResponse(BaseModel):
|
||||
type: Literal[
|
||||
"secret-input",
|
||||
"text-input",
|
||||
"select",
|
||||
"boolean",
|
||||
"app-selector",
|
||||
"model-selector",
|
||||
"array[tools]",
|
||||
] = Field(..., description="The type of the credentials")
|
||||
name: str = Field(..., description="The name of the credentials")
|
||||
scope: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | None = None
|
||||
required: bool = False
|
||||
default: int | str | float | bool | None = None
|
||||
options: list[TriggerProviderConfigOptionResponse] | None = None
|
||||
multiple: bool = False
|
||||
label: I18nObject | None = None
|
||||
help: I18nObject | None = None
|
||||
url: str | None = None
|
||||
placeholder: I18nObject | None = None
|
||||
|
||||
|
||||
class TriggerOAuthClientResponse(BaseModel):
|
||||
configured: bool
|
||||
system_configured: bool
|
||||
custom_configured: bool
|
||||
oauth_client_schema: list[TriggerProviderConfigResponse]
|
||||
custom_enabled: bool
|
||||
redirect_uri: str
|
||||
params: dict[str, Any]
|
||||
|
||||
|
||||
class TriggerProviderOpaqueResponse(RootModel[Any]):
|
||||
root: Any
|
||||
|
||||
|
||||
class TriggerProviderListResponse(RootModel[list[TriggerProviderApiEntity]]):
|
||||
root: list[TriggerProviderApiEntity]
|
||||
pass
|
||||
|
||||
|
||||
class TriggerSubscriptionListResponse(RootModel[list[TriggerProviderSubscriptionApiEntity]]):
|
||||
root: list[TriggerProviderSubscriptionApiEntity]
|
||||
class TriggerProviderSubscriptionListResponse(RootModel[list[TriggerProviderSubscriptionApiEntity]]):
|
||||
pass
|
||||
|
||||
|
||||
class TriggerSubscriptionBuilderCreateResponse(ResponseModel):
|
||||
subscription_builder: SubscriptionBuilderApiEntity
|
||||
|
||||
|
||||
class TriggerSubscriptionBuilderVerifyResponse(ResponseModel):
|
||||
class TriggerVerificationResponse(ResponseModel):
|
||||
verified: bool
|
||||
|
||||
|
||||
@@ -142,6 +94,26 @@ class TriggerSubscriptionBuilderLogsResponse(ResponseModel):
|
||||
logs: list[RequestLog]
|
||||
|
||||
|
||||
class TriggerOAuthAuthorizeResponse(ResponseModel):
|
||||
authorization_url: str
|
||||
subscription_builder_id: str
|
||||
subscription_builder: SubscriptionBuilderApiEntity
|
||||
|
||||
|
||||
class TriggerOAuthClientResponse(ResponseModel):
|
||||
configured: bool
|
||||
system_configured: bool
|
||||
custom_configured: bool
|
||||
oauth_client_schema: list[ProviderConfig]
|
||||
custom_enabled: bool
|
||||
redirect_uri: str
|
||||
params: dict[str, Any]
|
||||
|
||||
|
||||
class TriggerProviderErrorResponse(ResponseModel):
|
||||
error: str
|
||||
|
||||
|
||||
register_schema_models(
|
||||
console_ns,
|
||||
TriggerSubscriptionBuilderCreatePayload,
|
||||
@@ -151,27 +123,24 @@ register_schema_models(
|
||||
)
|
||||
register_response_schema_models(
|
||||
console_ns,
|
||||
BinaryFileResponse,
|
||||
RedirectResponse,
|
||||
SimpleResultResponse,
|
||||
TriggerOAuthAuthorizeResponse,
|
||||
TriggerOAuthClientResponse,
|
||||
TriggerProviderOpaqueResponse,
|
||||
TriggerProviderApiEntity,
|
||||
TriggerProviderErrorResponse,
|
||||
TriggerProviderListResponse,
|
||||
TriggerProviderSubscriptionApiEntity,
|
||||
TriggerSubscriptionListResponse,
|
||||
SubscriptionBuilderApiEntity,
|
||||
TriggerProviderSubscriptionListResponse,
|
||||
TriggerSubscriptionBuilderCreateResponse,
|
||||
TriggerSubscriptionBuilderVerifyResponse,
|
||||
RequestLog,
|
||||
TriggerSubscriptionBuilderLogsResponse,
|
||||
SubscriptionBuilderApiEntity,
|
||||
TriggerVerificationResponse,
|
||||
)
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/icon")
|
||||
class TriggerProviderIconApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[BinaryFileResponse.__name__])
|
||||
# response-contract:ignore binary trigger provider icon
|
||||
@console_ns.response(200, "Trigger provider icon")
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@@ -182,31 +151,45 @@ class TriggerProviderIconApi(Resource):
|
||||
|
||||
@console_ns.route("/workspaces/current/triggers")
|
||||
class TriggerProviderListApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderListResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger providers retrieved successfully",
|
||||
console_ns.models[TriggerProviderListResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
"""List all trigger providers for the current tenant"""
|
||||
return jsonable_encoder(TriggerProviderService.list_trigger_providers(tenant_id))
|
||||
return dump_response(TriggerProviderListResponse, TriggerProviderService.list_trigger_providers(tenant_id))
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/info")
|
||||
class TriggerProviderInfoApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderApiEntity.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger provider retrieved successfully",
|
||||
console_ns.models[TriggerProviderApiEntity.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, provider: str):
|
||||
"""Get info for a trigger provider"""
|
||||
return jsonable_encoder(TriggerProviderService.get_trigger_provider(tenant_id, TriggerProviderID(provider)))
|
||||
provider_entity = TriggerProviderService.get_trigger_provider(tenant_id, TriggerProviderID(provider))
|
||||
return provider_entity.model_dump(mode="json")
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/subscriptions/list")
|
||||
class TriggerSubscriptionListApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionListResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscriptions retrieved successfully",
|
||||
console_ns.models[TriggerProviderSubscriptionListResponse.__name__],
|
||||
)
|
||||
@console_ns.response(404, "Trigger provider not found", console_ns.models[TriggerProviderErrorResponse.__name__])
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -216,16 +199,18 @@ class TriggerSubscriptionListApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, user: Account, provider: str):
|
||||
"""List all trigger subscriptions for the current tenant's provider"""
|
||||
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
return dump_response(
|
||||
TriggerProviderSubscriptionListResponse,
|
||||
TriggerProviderService.list_trigger_provider_subscriptions(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
user=user,
|
||||
)
|
||||
),
|
||||
)
|
||||
except ValueError as e:
|
||||
return jsonable_encoder({"error": str(e)}), 404
|
||||
return TriggerProviderErrorResponse(error=str(e)).model_dump(mode="json"), 404
|
||||
except Exception as e:
|
||||
logger.exception("Error listing trigger providers", exc_info=e)
|
||||
raise
|
||||
@@ -236,7 +221,11 @@ class TriggerSubscriptionListApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderCreatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderCreateResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder created successfully",
|
||||
console_ns.models[TriggerSubscriptionBuilderCreateResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -246,6 +235,7 @@ class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str):
|
||||
"""Add a new subscription instance for a trigger provider"""
|
||||
|
||||
payload = TriggerSubscriptionBuilderCreatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
@@ -256,7 +246,9 @@ class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
provider_id=TriggerProviderID(provider),
|
||||
credential_type=credential_type,
|
||||
)
|
||||
return jsonable_encoder({"subscription_builder": subscription_builder})
|
||||
return TriggerSubscriptionBuilderCreateResponse(subscription_builder=subscription_builder).model_dump(
|
||||
mode="json"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("Error adding provider credential", exc_info=e)
|
||||
raise
|
||||
@@ -266,7 +258,11 @@ class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
"/workspaces/current/trigger-provider/<path:provider>/subscriptions/builder/<path:subscription_builder_id>",
|
||||
)
|
||||
class TriggerSubscriptionBuilderGetApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[SubscriptionBuilderApiEntity.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder retrieved successfully",
|
||||
console_ns.models[SubscriptionBuilderApiEntity.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -274,9 +270,8 @@ class TriggerSubscriptionBuilderGetApi(Resource):
|
||||
@account_initialization_required
|
||||
def get(self, provider: str, subscription_builder_id: str):
|
||||
"""Get a subscription instance for a trigger provider"""
|
||||
return jsonable_encoder(
|
||||
TriggerSubscriptionBuilderService.get_subscription_builder_by_id(subscription_builder_id)
|
||||
)
|
||||
subscription_builder = TriggerSubscriptionBuilderService.get_subscription_builder_by_id(subscription_builder_id)
|
||||
return subscription_builder.model_dump(mode="json")
|
||||
|
||||
|
||||
@console_ns.route(
|
||||
@@ -284,7 +279,11 @@ class TriggerSubscriptionBuilderGetApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderVerifyPayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderVerifyResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder verified successfully",
|
||||
console_ns.models[TriggerVerificationResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -294,11 +293,12 @@ class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str, subscription_builder_id: str):
|
||||
"""Verify and update a subscription instance for a trigger provider"""
|
||||
|
||||
payload = TriggerSubscriptionBuilderVerifyPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
# Use atomic update_and_verify to prevent race conditions
|
||||
return TriggerSubscriptionBuilderService.update_and_verify_builder(
|
||||
result = TriggerSubscriptionBuilderService.update_and_verify_builder(
|
||||
tenant_id=tenant_id,
|
||||
user_id=user.id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
@@ -307,6 +307,7 @@ class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
credentials=payload.credentials,
|
||||
),
|
||||
)
|
||||
return dump_response(TriggerVerificationResponse, result)
|
||||
except Exception as e:
|
||||
logger.exception("Error verifying provider credential", exc_info=e)
|
||||
raise ValueError(str(e)) from e
|
||||
@@ -317,7 +318,11 @@ class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderUpdateApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[SubscriptionBuilderApiEntity.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder updated successfully",
|
||||
console_ns.models[SubscriptionBuilderApiEntity.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -326,21 +331,20 @@ class TriggerSubscriptionBuilderUpdateApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, provider: str, subscription_builder_id: str):
|
||||
"""Update a subscription instance for a trigger provider"""
|
||||
|
||||
payload = TriggerSubscriptionBuilderUpdatePayload.model_validate(console_ns.payload or {})
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
TriggerSubscriptionBuilderService.update_trigger_subscription_builder(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
subscription_builder_id=subscription_builder_id,
|
||||
subscription_builder_updater=SubscriptionBuilderUpdater(
|
||||
name=payload.name,
|
||||
parameters=payload.parameters,
|
||||
properties=payload.properties,
|
||||
credentials=payload.credentials,
|
||||
),
|
||||
)
|
||||
)
|
||||
return TriggerSubscriptionBuilderService.update_trigger_subscription_builder(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
subscription_builder_id=subscription_builder_id,
|
||||
subscription_builder_updater=SubscriptionBuilderUpdater(
|
||||
name=payload.name,
|
||||
parameters=payload.parameters,
|
||||
properties=payload.properties,
|
||||
credentials=payload.credentials,
|
||||
),
|
||||
).model_dump(mode="json")
|
||||
except Exception as e:
|
||||
logger.exception("Error updating provider credential", exc_info=e)
|
||||
raise
|
||||
@@ -350,7 +354,11 @@ class TriggerSubscriptionBuilderUpdateApi(Resource):
|
||||
"/workspaces/current/trigger-provider/<path:provider>/subscriptions/builder/logs/<path:subscription_builder_id>",
|
||||
)
|
||||
class TriggerSubscriptionBuilderLogsApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderLogsResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder logs retrieved successfully",
|
||||
console_ns.models[TriggerSubscriptionBuilderLogsResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -358,9 +366,10 @@ class TriggerSubscriptionBuilderLogsApi(Resource):
|
||||
@account_initialization_required
|
||||
def get(self, provider: str, subscription_builder_id: str):
|
||||
"""Get the request logs for a subscription instance for a trigger provider"""
|
||||
|
||||
try:
|
||||
logs = TriggerSubscriptionBuilderService.list_logs(subscription_builder_id)
|
||||
return jsonable_encoder({"logs": [log.model_dump(mode="json") for log in logs]})
|
||||
return dump_response(TriggerSubscriptionBuilderLogsResponse, {"logs": logs})
|
||||
except Exception as e:
|
||||
logger.exception("Error getting request logs for subscription builder", exc_info=e)
|
||||
raise
|
||||
@@ -371,7 +380,9 @@ class TriggerSubscriptionBuilderLogsApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderBuildApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderOpaqueResponse.__name__])
|
||||
@console_ns.response(
|
||||
200, "Trigger subscription builder built successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -395,7 +406,7 @@ class TriggerSubscriptionBuilderBuildApi(Resource):
|
||||
properties=payload.properties,
|
||||
),
|
||||
)
|
||||
return 200
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
except Exception as e:
|
||||
logger.exception("Error building provider credential", exc_info=e)
|
||||
raise ValueError(str(e)) from e
|
||||
@@ -406,7 +417,9 @@ class TriggerSubscriptionBuilderBuildApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionUpdateApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderOpaqueResponse.__name__])
|
||||
@console_ns.response(
|
||||
200, "Trigger subscription updated successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -415,6 +428,7 @@ class TriggerSubscriptionUpdateApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, subscription_id: str):
|
||||
"""Update a subscription instance"""
|
||||
|
||||
request = TriggerSubscriptionBuilderUpdatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
subscription = TriggerProviderService.get_subscription_by_id(
|
||||
@@ -440,7 +454,7 @@ class TriggerSubscriptionUpdateApi(Resource):
|
||||
name=request.name,
|
||||
properties=request.properties,
|
||||
)
|
||||
return 200
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
|
||||
# For the rest cases(API_KEY, OAUTH2)
|
||||
# we need to call third party provider(e.g. GitHub) to rebuild the subscription
|
||||
@@ -452,7 +466,7 @@ class TriggerSubscriptionUpdateApi(Resource):
|
||||
credentials=request.credentials or subscription.credentials,
|
||||
parameters=request.parameters or subscription.parameters,
|
||||
)
|
||||
return 200
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
except Exception as e:
|
||||
@@ -473,6 +487,7 @@ class TriggerSubscriptionDeleteApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, subscription_id: str):
|
||||
"""Delete a subscription instance"""
|
||||
|
||||
try:
|
||||
with sessionmaker(db.engine).begin() as session:
|
||||
# Delete trigger provider subscription
|
||||
@@ -487,7 +502,7 @@ class TriggerSubscriptionDeleteApi(Resource):
|
||||
tenant_id=tenant_id,
|
||||
subscription_id=subscription_id,
|
||||
)
|
||||
return {"result": "success"}
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
except Exception as e:
|
||||
@@ -497,9 +512,10 @@ class TriggerSubscriptionDeleteApi(Resource):
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/subscriptions/oauth/authorize")
|
||||
class TriggerOAuthAuthorizeApi(Resource):
|
||||
# response-contract:ignore cookie-bearing Flask response
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Authorization URL retrieved successfully",
|
||||
"Trigger OAuth authorization URL generated successfully",
|
||||
console_ns.models[TriggerOAuthAuthorizeResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@@ -509,10 +525,12 @@ class TriggerOAuthAuthorizeApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, user: Account, provider: str):
|
||||
"""Initiate OAuth authorization flow for a trigger provider"""
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
plugin_id = provider_id.plugin_id
|
||||
provider_name = provider_id.provider_name
|
||||
tenant_id = tenant_id
|
||||
|
||||
# Get OAuth client configuration
|
||||
oauth_client_params = TriggerProviderService.get_oauth_client(
|
||||
@@ -556,15 +574,12 @@ class TriggerOAuthAuthorizeApi(Resource):
|
||||
system_credentials=oauth_client_params,
|
||||
)
|
||||
|
||||
# Create response with cookie
|
||||
response = make_response(
|
||||
jsonable_encoder(
|
||||
{
|
||||
"authorization_url": authorization_url_response.authorization_url,
|
||||
"subscription_builder_id": subscription_builder.id,
|
||||
"subscription_builder": subscription_builder,
|
||||
}
|
||||
)
|
||||
TriggerOAuthAuthorizeResponse(
|
||||
authorization_url=authorization_url_response.authorization_url,
|
||||
subscription_builder_id=subscription_builder.id,
|
||||
subscription_builder=subscription_builder,
|
||||
).model_dump(mode="json")
|
||||
)
|
||||
response.set_cookie(
|
||||
"context_id",
|
||||
@@ -583,11 +598,8 @@ class TriggerOAuthAuthorizeApi(Resource):
|
||||
|
||||
@console_ns.route("/oauth/plugin/<path:provider>/trigger/callback")
|
||||
class TriggerOAuthCallbackApi(Resource):
|
||||
@console_ns.response(
|
||||
302,
|
||||
"Redirect to console OAuth callback page",
|
||||
console_ns.models[RedirectResponse.__name__],
|
||||
)
|
||||
# response-contract:ignore redirect response
|
||||
@console_ns.response(302, "Redirect to OAuth callback page")
|
||||
@setup_required
|
||||
def get(self, provider: str):
|
||||
"""Handle OAuth callback for trigger provider"""
|
||||
@@ -653,7 +665,11 @@ class TriggerOAuthCallbackApi(Resource):
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/oauth/client")
|
||||
class TriggerOAuthClientManageApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerOAuthClientResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger OAuth client retrieved successfully",
|
||||
console_ns.models[TriggerOAuthClientResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@is_admin_or_owner_required
|
||||
@@ -662,6 +678,7 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, provider: str):
|
||||
"""Get OAuth client configuration for a provider"""
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
|
||||
@@ -682,24 +699,24 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
)
|
||||
provider_controller = TriggerManager.get_trigger_provider(tenant_id, provider_id)
|
||||
redirect_uri = f"{dify_config.CONSOLE_API_URL}/console/api/oauth/plugin/{provider}/trigger/callback"
|
||||
return jsonable_encoder(
|
||||
{
|
||||
"configured": bool(custom_params or system_client_exists),
|
||||
"system_configured": system_client_exists,
|
||||
"custom_configured": bool(custom_params),
|
||||
"oauth_client_schema": provider_controller.get_oauth_client_schema(),
|
||||
"custom_enabled": is_custom_enabled,
|
||||
"redirect_uri": redirect_uri,
|
||||
"params": custom_params or {},
|
||||
}
|
||||
)
|
||||
return TriggerOAuthClientResponse(
|
||||
configured=bool(custom_params or system_client_exists),
|
||||
system_configured=system_client_exists,
|
||||
custom_configured=bool(custom_params),
|
||||
oauth_client_schema=provider_controller.get_oauth_client_schema(),
|
||||
custom_enabled=is_custom_enabled,
|
||||
redirect_uri=redirect_uri,
|
||||
params=dict(custom_params or {}),
|
||||
).model_dump(mode="json")
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("Error getting OAuth client", exc_info=e)
|
||||
raise
|
||||
|
||||
@console_ns.expect(console_ns.models[TriggerOAuthClientPayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__])
|
||||
@console_ns.response(
|
||||
200, "Trigger OAuth client saved successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@is_admin_or_owner_required
|
||||
@@ -708,16 +725,18 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, provider: str):
|
||||
"""Configure custom OAuth client for a provider"""
|
||||
|
||||
payload = TriggerOAuthClientPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
return TriggerProviderService.save_custom_oauth_client_params(
|
||||
result = TriggerProviderService.save_custom_oauth_client_params(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=provider_id,
|
||||
client_params=payload.client_params,
|
||||
enabled=payload.enabled,
|
||||
)
|
||||
return dump_response(SimpleResultResponse, result)
|
||||
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
@@ -725,22 +744,26 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
logger.exception("Error configuring OAuth client", exc_info=e)
|
||||
raise
|
||||
|
||||
@console_ns.response(
|
||||
200, "Trigger OAuth client deleted successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@is_admin_or_owner_required
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_PREFERENCES, resource_required=False)
|
||||
@account_initialization_required
|
||||
@console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__])
|
||||
@with_current_tenant_id
|
||||
def delete(self, tenant_id: str, provider: str):
|
||||
"""Remove custom OAuth client configuration"""
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
|
||||
return TriggerProviderService.delete_custom_oauth_client_params(
|
||||
result = TriggerProviderService.delete_custom_oauth_client_params(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=provider_id,
|
||||
)
|
||||
return dump_response(SimpleResultResponse, result)
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
except Exception as e:
|
||||
@@ -753,7 +776,11 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionVerifyApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderVerifyPayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderVerifyResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription verified successfully",
|
||||
console_ns.models[TriggerVerificationResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@@ -763,6 +790,7 @@ class TriggerSubscriptionVerifyApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str, subscription_id: str):
|
||||
"""Verify credentials for an existing subscription (edit mode only)"""
|
||||
|
||||
verify_request = TriggerSubscriptionBuilderVerifyPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
@@ -773,7 +801,7 @@ class TriggerSubscriptionVerifyApi(Resource):
|
||||
subscription_id=subscription_id,
|
||||
credentials=verify_request.credentials,
|
||||
)
|
||||
return result
|
||||
return dump_response(TriggerVerificationResponse, result)
|
||||
except ValueError as e:
|
||||
logger.warning("Credential verification failed", exc_info=e)
|
||||
raise BadRequest(str(e)) from e
|
||||
|
||||
Reference in New Issue
Block a user