Repository: juspay/hyperswitch
File: crates/router/src/core/payments/helpers.rs (Rust)

Code before:
    state: &SessionState,
) -> RouterResult<bool> {
    let db = &*state.store;
    let org_key = org_id.get_authentication_service_eligible_key();
    let org_eligible = db
        .find_config_by_key(&org_key)
        .await
        .inspect_err(|error| {
            logger::error!(?error, "Failed to fetch `{org_key}` config from DB");
        })
        .is_ok_and(|c| c.config.to_lowercase() == "true");

    // Early return if org is eligible - no need to check merchant
    if org_eligible {
        return Ok(true);
    }

    // Only fetch merchant config if org is not eligible
    let merchant_key = merchant_id.get_authentication_service_eligible_key();
    let merchant_eligible = db
        .find_config_by_key(&merchant_key)
        .await
        .inspect_err(|error| {
            logger::error!(?error, "Failed to fetch `{merchant_key}` config from DB");
        })
        .is_ok_and(|c| c.config.to_lowercase() == "true");

    Ok(merchant_eligible)
}

#[cfg(feature = "v1")]
pub async fn validate_allowed_payment_method_types_request(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    processor: &domain::Processor,
    allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    if let Some(allowed_payment_method_types) = allowed_payment_method_types {
        let db = &*state.store;
        let all_connector_accounts = db
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                processor.get_account().get_id(),
                false,
                processor.get_key_store(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to fetch merchant connector account for given merchant id")?;

        let filtered_connector_accounts = all_connector_accounts
            .filter_based_on_profile_and_connector_type(

Review comment (suggestion):
instead of early return like this can we use `async_unwrap_or_else` to check on merchant eligibility. Makes the code more functional

Code after:
///    - Org = "true" → returns true (authentication enabled)
///    - Org = "false" → returns false (authentication disabled, merchant config ignored)
/// 2. If org-level config is missing or fails to fetch, fallback to merchant-level config
///    - Merchant = "true" → returns true
///    - Merchant = "false" or missing → returns false
///
/// This ensures parent (org) rules take precedence over child (merchant) configurations
pub async fn is_merchant_eligible_authentication_service(
    merchant_id: &id_type::MerchantId,
    org_id: &id_type::OrganizationId,
    state: &SessionState,
) -> RouterResult<bool> {
    let db = &*state.store;
    let org_key = org_id.get_authentication_service_eligible_key();
    let org_eligible = db
        .find_config_by_key(&org_key)
        .await
        .inspect_err(|error| {
            logger::error!(?error, "Failed to fetch `{org_key}` config from DB");
        })
        .ok()
        .map(|c| c.config.to_lowercase() == "true");

    Ok(org_eligible
        .async_unwrap_or_else(|| async {
            let merchant_key = merchant_id.get_authentication_service_eligible_key();
            db.find_config_by_key(&merchant_key)
                .await
                .inspect_err(|error| {
                    logger::error!(?error, "Failed to fetch `{merchant_key}` config from DB");
                })
                .ok()
                .map(|c| c.config.to_lowercase() == "true")
                .unwrap_or(false)
        })
        .await)
}

#[cfg(feature = "v1")]
pub async fn validate_allowed_payment_method_types_request(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    processor: &domain::Processor,
    allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    if let Some(allowed_payment_method_types) = allowed_payment_method_types {
        let db = &*state.store;
        let all_connector_accounts = db
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                processor.get_account().get_id(),
                false,