From 9e990c5ccd91b907847cb19cefead49d36fc16a8 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 29 Dec 2025 19:49:24 +0800 Subject: [PATCH] feat(api): add validation to ensure at least one field is provided in TriggerSubscriptionUpdateRequest - Introduced a model validator in TriggerSubscriptionUpdateRequest to enforce that at least one of the fields (name, credentials, parameters, properties) must be provided. - Refactored the TriggerSubscriptionUpdateApi to use the validated request object and simplified the logic for updating subscriptions based on the credential type. - Updated the credential type check in TriggerProviderService to use a set for better performance and clarity. --- .../console/workspace/trigger_providers.py | 38 +++++++++---------- .../trigger/trigger_provider_service.py | 4 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/api/controllers/console/workspace/trigger_providers.py b/api/controllers/console/workspace/trigger_providers.py index 81cb11fc2e..886e04e06d 100644 --- a/api/controllers/console/workspace/trigger_providers.py +++ b/api/controllers/console/workspace/trigger_providers.py @@ -4,7 +4,7 @@ from typing import Any from flask import make_response, redirect, request from flask_restx import Resource, reqparse -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, model_validator from sqlalchemy.orm import Session from werkzeug.exceptions import BadRequest, Forbidden @@ -43,6 +43,12 @@ class TriggerSubscriptionUpdateRequest(BaseModel): parameters: Mapping[str, Any] | None = Field(default=None, description="The parameters for the subscription") properties: Mapping[str, Any] | None = Field(default=None, description="The properties for the subscription") + @model_validator(mode="after") + def check_at_least_one_field(self): + if all(v is None for v in (self.name, self.credentials, self.parameters, self.properties)): + raise ValueError("At least one of name, credentials, parameters, or properties must be provided") + return self + class TriggerSubscriptionVerifyRequest(BaseModel): """Request payload for verifying subscription credentials.""" @@ -332,7 +338,7 @@ class TriggerSubscriptionUpdateApi(Resource): user = current_user assert user.current_tenant_id is not None - args = TriggerSubscriptionUpdateRequest.model_validate(console_ns.payload) + request = TriggerSubscriptionUpdateRequest.model_validate(console_ns.payload) subscription = TriggerProviderService.get_subscription_by_id( tenant_id=user.current_tenant_id, @@ -344,33 +350,27 @@ class TriggerSubscriptionUpdateApi(Resource): provider_id = TriggerProviderID(subscription.provider_id) try: - # for rename only, update the name - if args.name is not None and not any((args.credentials, args.parameters, args.properties)): + # For rename only, just update the name + rename = request.name is not None and not any((request.credentials, request.parameters, request.properties)) + # When credential type is UNAUTHORIZED, it indicates the subscription was manually created + manually_created = subscription.credential_type == CredentialType.UNAUTHORIZED + if rename or manually_created: TriggerProviderService.update_trigger_subscription( tenant_id=user.current_tenant_id, subscription_id=subscription_id, - name=args.name, + name=request.name, + properties=request.properties, ) return 200 - # for manually created subscription, only update the name and properties - if subscription.credential_type == CredentialType.UNAUTHORIZED: - TriggerProviderService.update_trigger_subscription( - tenant_id=user.current_tenant_id, - subscription_id=subscription_id, - name=args.name, - properties=args.properties, - ) - return 200 - - # rebuild for create automatically by the provider + # For the rest cases(API_KEY, OAUTH2), call third party provider to rebuild the subscription TriggerProviderService.rebuild_trigger_subscription( tenant_id=user.current_tenant_id, - name=args.name, + name=request.name, provider_id=provider_id, subscription_id=subscription_id, - credentials=args.credentials or subscription.credentials, - parameters=args.parameters or subscription.parameters, + credentials=request.credentials or subscription.credentials, + parameters=request.parameters or subscription.parameters, ) return 200 except ValueError as e: diff --git a/api/services/trigger/trigger_provider_service.py b/api/services/trigger/trigger_provider_service.py index d1c07dd3cc..3bca4813be 100644 --- a/api/services/trigger/trigger_provider_service.py +++ b/api/services/trigger/trigger_provider_service.py @@ -875,8 +875,8 @@ class TriggerProviderService: if not subscription: raise ValueError(f"Subscription {subscription_id} not found") - credential_type = CredentialType.of(subscription.credential_type) - if credential_type not in [CredentialType.OAUTH2, CredentialType.API_KEY]: + credential_type = subscription.credential_type + if credential_type not in {CredentialType.OAUTH2, CredentialType.API_KEY}: raise ValueError(f"Credential type {credential_type} not supported for auto creation") # Delete the previous subscription