feat: add Creators Platform helper for DSL upload and OAuth redirect (Vibe Kanban) (#32232)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Junyan Chin
2026-02-11 21:10:48 +08:00
committed by GitHub
parent 98d2eb6579
commit 2bf767d5f7
30 changed files with 258 additions and 1 deletions

View File

@@ -627,6 +627,11 @@ INNER_API_KEY_FOR_PLUGIN=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y
MARKETPLACE_ENABLED=true
MARKETPLACE_API_URL=https://marketplace.dify.ai
# Creators Platform configuration
CREATORS_PLATFORM_FEATURES_ENABLED=true
CREATORS_PLATFORM_API_URL=https://creators.dify.ai
CREATORS_PLATFORM_OAUTH_CLIENT_ID=
# Endpoint configuration
ENDPOINT_URL_TEMPLATE=http://localhost:5002/e/{hook_id}

View File

@@ -293,6 +293,27 @@ class MarketplaceConfig(BaseSettings):
)
class CreatorsPlatformConfig(BaseSettings):
"""
Configuration for creators platform
"""
CREATORS_PLATFORM_FEATURES_ENABLED: bool = Field(
description="Enable or disable creators platform features",
default=True,
)
CREATORS_PLATFORM_API_URL: HttpUrl = Field(
description="Creators Platform API URL",
default=HttpUrl("https://creators.dify.ai"),
)
CREATORS_PLATFORM_OAUTH_CLIENT_ID: str = Field(
description="OAuth client_id for the Creators Platform app registered in Dify",
default="",
)
class EndpointConfig(BaseSettings):
"""
Configuration for various application endpoints and URLs
@@ -1396,6 +1417,7 @@ class FeatureConfig(
PluginConfig,
CliApiConfig,
MarketplaceConfig,
CreatorsPlatformConfig,
DataSetConfig,
EndpointConfig,
FileAccessConfig,

View File

@@ -736,6 +736,46 @@ class AppExportBundleApi(Resource):
return result.model_dump(mode="json")
@console_ns.route("/apps/<uuid:app_id>/publish-to-creators-platform")
class AppPublishToCreatorsPlatformApi(Resource):
@get_app_model
@setup_required
@login_required
@account_initialization_required
@edit_permission_required
def post(self, app_model):
"""Bundle the app DSL and upload to Creators Platform, returning a redirect URL."""
import httpx
from configs import dify_config
from core.helper.creators import get_redirect_url, upload_dsl
from services.app_bundle_service import AppBundleService
if not dify_config.CREATORS_PLATFORM_FEATURES_ENABLED:
return {"message": "Creators Platform is not enabled"}, 403
current_user, _ = current_account_with_tenant()
# 1. Export the app bundle (DSL + assets) to a temporary zip
bundle_result = AppBundleService.export_bundle(
app_model=app_model,
account_id=str(current_user.id),
include_secret=False,
)
# 2. Download the zip from the temporary URL
download_response = httpx.get(bundle_result.download_url, timeout=60, follow_redirects=True)
download_response.raise_for_status()
# 3. Upload to Creators Platform
claim_code = upload_dsl(download_response.content, filename=bundle_result.filename)
# 4. Generate redirect URL (with optional OAuth code)
redirect_url = get_redirect_url(str(current_user.id), claim_code)
return {"redirect_url": redirect_url}
@console_ns.route("/apps/<uuid:app_id>/name")
class AppNameApi(Resource):
@console_ns.doc("check_app_name")

View File

@@ -0,0 +1,75 @@
"""
Helper module for Creators Platform integration.
Provides functionality to upload DSL files to the Creators Platform
and generate redirect URLs with OAuth authorization codes.
"""
import logging
from urllib.parse import urlencode
import httpx
from yarl import URL
from configs import dify_config
logger = logging.getLogger(__name__)
creators_platform_api_url = URL(str(dify_config.CREATORS_PLATFORM_API_URL))
def upload_dsl(dsl_file_bytes: bytes, filename: str = "template.yaml") -> str:
"""Upload a DSL file to the Creators Platform anonymous upload endpoint.
Args:
dsl_file_bytes: Raw bytes of the DSL file (YAML or ZIP).
filename: Original filename for the upload.
Returns:
The claim_code string used to retrieve the DSL later.
Raises:
httpx.HTTPStatusError: If the upload request fails.
ValueError: If the response does not contain a valid claim_code.
"""
url = str(creators_platform_api_url / "api/v1/templates/anonymous-upload")
response = httpx.post(url, files={"file": (filename, dsl_file_bytes)}, timeout=30)
response.raise_for_status()
data = response.json()
claim_code = data.get("data", {}).get("claim_code")
if not claim_code:
raise ValueError("Creators Platform did not return a valid claim_code")
return claim_code
def get_redirect_url(user_account_id: str, claim_code: str) -> str:
"""Generate the redirect URL to the Creators Platform frontend.
Redirects to the Creators Platform root page with the dsl_claim_code.
If CREATORS_PLATFORM_OAUTH_CLIENT_ID is configured (Dify Cloud),
also signs an OAuth authorization code so the frontend can
automatically authenticate the user via the OAuth callback.
For self-hosted Dify without OAuth client_id configured, only the
dsl_claim_code is passed and the user must log in manually.
Args:
user_account_id: The Dify user account ID.
claim_code: The claim_code obtained from upload_dsl().
Returns:
The full redirect URL string.
"""
base_url = str(dify_config.CREATORS_PLATFORM_API_URL).rstrip("/")
params: dict[str, str] = {"dsl_claim_code": claim_code}
client_id = str(dify_config.CREATORS_PLATFORM_OAUTH_CLIENT_ID or "")
if client_id:
from services.oauth_server import OAuthServerService
oauth_code = OAuthServerService.sign_oauth_authorization_code(client_id, user_account_id)
params["oauth_code"] = oauth_code
return f"{base_url}?{urlencode(params)}"

View File

@@ -177,6 +177,7 @@ class SystemFeatureModel(BaseModel):
trial_models: list[str] = []
enable_trial_app: bool = False
enable_explore_banner: bool = False
enable_creators_platform: bool = False
class FeatureService:
@@ -238,6 +239,9 @@ class FeatureService:
if dify_config.MARKETPLACE_ENABLED:
system_features.enable_marketplace = True
if dify_config.CREATORS_PLATFORM_FEATURES_ENABLED:
system_features.enable_creators_platform = True
return system_features
@classmethod