hyperswitch icon indicating copy to clipboard operation
hyperswitch copied to clipboard

feat(connector_cloning): Create API for cloning connectors between merchants and profiles.

Open ThisIsMani opened this issue 11 months ago • 1 comments

Type of Change

  • [ ] Bugfix
  • [x] New feature
  • [ ] Enhancement
  • [ ] Refactoring
  • [ ] Dependency updates
  • [ ] Documentation
  • [ ] CI/CD

Description

This branch primarily introduces the Connector Cloning feature. Key changes include:

  • API: Added new API models (CloneConnectorRequest, CloneConnectorSource, CloneConnectorDestination) and a new API endpoint (/user/clone_connector).
  • Core Logic: Implemented the clone_connector function in crates/router/src/core/user.rs to handle the cloning process, supported by a helper function build_cloned_connector_create_request in crates/router/src/utils/user.rs.
  • Configuration: Introduced a clone_connector_whitelist configuration section in settings.rs and added it to example/deployment config files (config.example.toml, development.toml, etc.) to control which merchants and connectors are allowed for cloning.
  • Authorization & Roles:
    • Added new internal permission group (InternalManage), parent group (Internal), and resource (InternalConnector).
    • Added a new predefined internal role (internal_demo) possibly for demonstrating or testing the clone feature.
    • Updated authorization info functions (get_group_authorization_info, get_parent_group_description, get_resource_name) to handle internal groups/resources gracefully (returning None for user-facing descriptions).
    • Updated role validation to prevent adding InternalManage to custom roles.
  • Internal User Creation: Added role_id field to CreateInternalUserRequest.

Additional Changes

  • [x] This PR modifies the API contract (new endpoint and models for cloning).
  • [ ] This PR modifies the database schema
  • [x] This PR modifies application configuration/environment variables (new clone_connector_whitelist section).
  • config/config.example.toml
  • config/deployments/env_specific.toml
  • config/development.toml
  • config/docker_compose.toml
  • crates/router/src/configs/settings.rs

Motivation and Context

Closes https://github.com/juspay/hyperswitch-control-center/issues/2921

How did you test it?

  1. Clone Connector API
  • Request
    curl --location '<YOUR_BASE_URL>/user/clone_connector' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <INTERNAL_DEMO_USER_AUTH_TOKEN>' \
    --data '{
      "source": {
        "mca_id": "<SOURCE_MCA_ID>",
        "profile_id": "<SOURCE_PROFILE_ID>",
        "merchant_id": "<SOURCE_MERCHANT_ID>"
      },
      "destination": {
        "connector_label": "Cloned Stripe Connector",
        "profile_id": "<DESTINATION_PROFILE_ID>",
        "merchant_id": "<DESTINATION_MERCHANT_ID>"
      }
    }'
    
  • Response: Same as Connector Create response
    {
      "connector_type": "processor",
      "connector_name": "stripe",
      "connector_label": "Cloned Stripe Connector",
      "merchant_connector_id": "mca_xxxxxxxxxxxxxxxx",
      "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "sk_test_****************************************xyz"
      },
      "test_mode": true,
      "disabled": false,
      "payment_methods_enabled": [
        {
          "payment_method": "card",
          "payment_method_types": [
            {
              "payment_method_type": "credit",
              "card_networks": ["Visa", "Mastercard"],
              "minimum_amount": 1,
              "maximum_amount": 68607706,
              "recurring_enabled": true,
              "installment_payment_enabled": true
            },
            {
              "payment_method_type": "debit",
              "card_networks": ["Visa", "Mastercard"],
              "minimum_amount": 1,
              "maximum_amount": 68607706,
              "recurring_enabled": true,
              "installment_payment_enabled": true
            }
          ],
          "payment_experience": "redirect_to_url",
          "accepted_currencies": ["USD", "EUR", "GBP"],
          "accepted_countries": ["US", "GB", "FR"]
        }
      ],
      "metadata": null,
      "business_country": ["US"],
      "business_label": "default",
      "business_sub_label": null,
      "frm_configs": null,
      "connector_webhook_details": {
        "merchant_secret": "whsec_*************************"
      },
      "profile_id": "<DESTINATION_PROFILE_ID>",
      "applepay_verified_domains": null,
      "pm_auth_config": null,
      "status": "active",
      "connector_wallets_details": null,
      "additional_merchant_data": null
    }
    
  1. Creating Internal Demo User
  • Request
    curl --location '<YOUR_BASE_URL>/user/internal_signup' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <ADMIN_API_KEY>' \
    --data-raw '{
      "name": "Demo User",
      "email": "[email protected]",
      "password": "<USER_PASSWORD>",
      "role_id": "internal_demo"
    }'
    
  • Response: 200 OK

Checklist

  • [x] I formatted the code cargo +nightly fmt --all
  • [x] I addressed lints thrown by cargo clippy
  • [x] I reviewed the submitted code
  • [ ] I added unit tests for my changes where possible

ThisIsMani avatar May 02 '25 13:05 ThisIsMani

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/services/authorization/info.rs  86% smaller
  crates/router/src/services/authorization/permissions.rs  86% smaller
  crates/router/src/routes/lock_utils.rs  86% smaller
  crates/router/src/core/user_role.rs  73% smaller
  crates/api_models/src/events/user.rs  61% smaller
  crates/router/src/utils/user_role.rs  58% smaller
  crates/router/src/services/authorization/permission_groups.rs  32% smaller
  crates/router/src/core/user.rs  6% smaller
  config/config.example.toml Unsupported file format
  config/deployments/env_specific.toml Unsupported file format
  config/development.toml Unsupported file format
  config/docker_compose.toml Unsupported file format
  crates/api_models/src/user.rs  0% smaller
  crates/common_enums/src/enums.rs  0% smaller
  crates/common_utils/src/consts.rs  0% smaller
  crates/router/src/configs/secrets_transformers.rs  0% smaller
  crates/router/src/configs/settings.rs  0% smaller
  crates/router/src/core/errors/user.rs  0% smaller
  crates/router/src/core/user_role/role.rs  0% smaller
  crates/router/src/routes/app.rs  0% smaller
  crates/router/src/routes/user.rs  0% smaller
  crates/router/src/services/authorization/roles.rs  0% smaller
  crates/router/src/services/authorization/roles/predefined_roles.rs  0% smaller
  crates/router/src/utils/user.rs  0% smaller
  crates/router_env/src/logger/types.rs  0% smaller

semanticdiff-com[bot] avatar May 02 '25 13:05 semanticdiff-com[bot]