Issue 540 - fix: remove hardcoded value and add test cases
This commit is contained in:
@@ -1,162 +1,142 @@
|
||||
# DeDi Registry Plugin
|
||||
|
||||
A **registry type plugin** for Beckn-ONIX that integrates with DeDi (Decentralized Digital Infrastructure) registry services.
|
||||
A **registry type plugin** for Beckn-ONIX that integrates with DeDi (Decentralized Digital Infrastructure) registry services via the new DeDi Wrapper API.
|
||||
|
||||
## Overview
|
||||
|
||||
The DeDi Registry plugin is a **registry implementation** that enables Beckn-ONIX to lookup participant records from remote DeDi registries via REST API calls.
|
||||
The DeDi Registry plugin implements the `RegistryLookup` interface to retrieve public keys and participant information from DeDi registry services. It's used by the KeyManager for **signature validation of incoming requests** from other network participants.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
registry:
|
||||
id: dediregistry
|
||||
config:
|
||||
baseURL: "https://dedi-api.example.com"
|
||||
apiKey: "your-bearer-token"
|
||||
namespaceID: "76EU8BF1gzRGGatgw7wZZb7nEVx77XSwkKDv4UDLdxh8ztty4zmbYU"
|
||||
registryName: "dedi_registry"
|
||||
timeout: "30" # seconds
|
||||
registry:
|
||||
id: dediregistry
|
||||
config:
|
||||
url: "https://dedi-wrapper.example.com/dedi"
|
||||
registryName: "subscribers.beckn.one"
|
||||
timeout: 30
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
| Parameter | Required | Description | Default |
|
||||
|-----------|----------|-------------|---------|
|
||||
| `baseURL` | Yes | DeDi registry API base URL | - |
|
||||
| `apiKey` | Yes | Bearer token for API authentication | - |
|
||||
| `namespaceID` | Yes | DeDi namespace identifier | - |
|
||||
| `registryName` | Yes | Registry name to query | - |
|
||||
| `timeout` | No | Request timeout in seconds | 30 |
|
||||
| `url` | Yes | DeDi wrapper API base URL (include /dedi path) | - |
|
||||
| `registryName` | Yes | Registry name for lookup path | - |
|
||||
| `timeout` | No | Request timeout in seconds | Client default |
|
||||
|
||||
## Usage
|
||||
## API Integration
|
||||
|
||||
### In Module Configuration
|
||||
### DeDi Wrapper API Format
|
||||
```
|
||||
GET {url}/lookup/{subscriber_id}/{registryName}/{key_id}
|
||||
```
|
||||
|
||||
**Example**: `https://dedi-wrapper.com/dedi/lookup/bpp.example.com/subscribers.beckn.one/key-1`
|
||||
|
||||
### Authentication
|
||||
**No authentication required** - DeDi wrapper API is public.
|
||||
|
||||
### Expected Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Record retrieved from registry cache",
|
||||
"data": {
|
||||
"record_id": "76EU8vY9TkuJ9T62Sc3FyQLf5Kt9YAVgbZhryX6mFi56ipefkP9d9a",
|
||||
"details": {
|
||||
"url": "http://dev.np2.com/beckn/bap",
|
||||
"type": "BAP",
|
||||
"domain": "energy",
|
||||
"subscriber_id": "dev.np2.com",
|
||||
"signing_public_key": "384qqkIIpxo71WaJPsWqQNWUDGAFnfnJPxuDmtuBiLo=",
|
||||
"encr_public_key": "test-encr-key"
|
||||
},
|
||||
"created_at": "2025-10-27T11:45:27.963Z",
|
||||
"updated_at": "2025-10-27T11:46:23.563Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Context
|
||||
|
||||
### Signature Validation Flow
|
||||
```
|
||||
1. External ONIX → Request with Authorization header
|
||||
2. ONIX Receiver → parseHeader() extracts subscriberID/keyID
|
||||
3. validateSign step → KeyManager.LookupNPKeys()
|
||||
4. KeyManager → DeDiRegistry.Lookup() with extracted values
|
||||
5. DeDi Registry → GET {url}/lookup/{subscriberID}/{registryName}/{keyID}
|
||||
6. DeDi Wrapper → Returns participant public keys
|
||||
7. SignValidator → Validates signature using retrieved public key
|
||||
```
|
||||
|
||||
### Module Configuration Example
|
||||
|
||||
```yaml
|
||||
modules:
|
||||
- name: bapTxnReceiver
|
||||
- name: bppTxnReceiver
|
||||
handler:
|
||||
plugins:
|
||||
registry:
|
||||
id: dediregistry
|
||||
config:
|
||||
baseURL: "https://dedi-registry.example.com"
|
||||
apiKey: "your-api-key"
|
||||
namespaceID: "beckn-network"
|
||||
registryName: "participants"
|
||||
url: "https://dedi-wrapper.example.com/dedi"
|
||||
registryName: "subscribers.beckn.one"
|
||||
timeout: 30
|
||||
steps:
|
||||
- validateSign # Required for registry lookup
|
||||
- addRoute
|
||||
```
|
||||
|
||||
### In Code
|
||||
## Field Mapping
|
||||
|
||||
```go
|
||||
// Load DeDi registry plugin (same as any registry plugin)
|
||||
dediRegistry, err := manager.Registry(ctx, &plugin.Config{
|
||||
ID: "dediregistry", // Plugin ID specifies DeDi implementation
|
||||
Config: map[string]string{
|
||||
"baseURL": "https://dedi-registry.example.com",
|
||||
"apiKey": "your-api-key",
|
||||
"namespaceID": "beckn-network",
|
||||
"registryName": "participants",
|
||||
},
|
||||
})
|
||||
|
||||
// Lookup participant with dynamic subscriber ID (from request context)
|
||||
subscription := &model.Subscription{
|
||||
Subscriber: model.Subscriber{
|
||||
SubscriberID: "bap-network", // Extracted from Authorization header or request body
|
||||
},
|
||||
}
|
||||
results, err := dediRegistry.Lookup(ctx, subscription)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract public key from result (standard Beckn format)
|
||||
if len(results) > 0 {
|
||||
publicKey := results[0].SigningPublicKey
|
||||
subscriberID := results[0].SubscriberID
|
||||
}
|
||||
```
|
||||
|
||||
## API Integration
|
||||
|
||||
### DeDi API URL Pattern
|
||||
```
|
||||
{baseURL}/dedi/lookup/{namespaceID}/{registryName}/{subscriberID}
|
||||
```
|
||||
|
||||
**Example**: `https://dedi-api.com/dedi/lookup/76EU8BF1gzRGGatgw7wZZb7nEVx77XSwkKDv4UDLdxh8ztty4zmbYU/dedi_registry/bap-network`
|
||||
|
||||
### Authentication
|
||||
```
|
||||
Authorization: Bearer {apiKey}
|
||||
```
|
||||
|
||||
### Expected DeDi Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Resource retrieved successfully",
|
||||
"data": {
|
||||
"namespace": "dediregistry",
|
||||
"namespace_id": "76EU8BF1gzRGGatgw7wZZb7nEVx77XSwkKDv4UDLdxh8ztty4zmbYU",
|
||||
"registry_name": "dedi_registry",
|
||||
"record_name": "bap-network",
|
||||
"details": {
|
||||
"key_id": "b692d295-5425-40f5-af77-d62646841dca",
|
||||
"signing_public_key": "YK3Xqc83Bpobc1UT0ObAe6mBJMiAOkceIsNtmph9WTc=",
|
||||
"encr_public_key": "YK3Xqc83Bpobc1UT0ObAe6mBJMiAOkceIsNtmph9WTc=",
|
||||
"status": "SUBSCRIBED",
|
||||
"created": "2024-01-15T10:00:00Z",
|
||||
"updated": "2024-01-15T10:00:00Z",
|
||||
"valid_from": "2024-01-01T00:00:00Z",
|
||||
"valid_until": "2025-12-31T23:59:59Z"
|
||||
},
|
||||
"state": "live",
|
||||
"created_at": "2025-10-09T06:09:48.295Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Field Mapping to Beckn Subscription
|
||||
|
||||
| DeDi Field | Beckn Field | Description |
|
||||
|------------|-------------|-------------|
|
||||
| `data.record_name` | `subscriber_id` | Participant identifier |
|
||||
| `data.details.key_id` | `key_id` | Unique key identifier |
|
||||
| DeDi Wrapper Field | Beckn Field | Description |
|
||||
|-------------------|-------------|-------------|
|
||||
| `data.details.subscriber_id` | `subscriber_id` | Participant identifier |
|
||||
| `{key_id from URL}` | `key_id` | Unique key identifier |
|
||||
| `data.details.signing_public_key` | `signing_public_key` | Public key for signature verification |
|
||||
| `data.details.encr_public_key` | `encr_public_key` | Public key for encryption |
|
||||
| `data.details.status` | `status` | Subscription status |
|
||||
| `data.details.created` | `created` | Creation timestamp |
|
||||
| `data.details.updated` | `updated` | Last update timestamp |
|
||||
| `data.details.valid_from` | `valid_from` | Key validity start |
|
||||
| `data.details.valid_until` | `valid_until` | Key validity end |
|
||||
| `data.is_revoked` | `status` | Not mapped (Status field will be empty) |
|
||||
| `data.created_at` | `created` | Creation timestamp |
|
||||
| `data.updated_at` | `updated` | Last update timestamp |
|
||||
|
||||
### Lookup Flow
|
||||
## Features
|
||||
|
||||
1. **Request Processing**: Plugin extracts `subscriber_id` from incoming request
|
||||
2. **API Call**: Makes GET request to DeDi API with static config + dynamic subscriber ID
|
||||
3. **Response Parsing**: Extracts data from `data.details` object
|
||||
4. **Format Conversion**: Maps DeDi fields to Beckn Subscription format
|
||||
5. **Return**: Returns array of Subscription objects
|
||||
- **No Authentication Required**: DeDi wrapper API doesn't require API keys
|
||||
- **GET Request Format**: Simple URL-based parameter passing
|
||||
- **Comprehensive Error Handling**: Validates required fields and HTTP responses
|
||||
- **Simplified Response**: Focuses on public key retrieval for signature validation
|
||||
- **Retry Support**: Built-in retry mechanism for network resilience
|
||||
|
||||
## Testing
|
||||
|
||||
Run plugin tests:
|
||||
Run the test suite:
|
||||
|
||||
```bash
|
||||
go test ./pkg/plugin/implementation/dediregistry -v
|
||||
```
|
||||
|
||||
Test coverage includes:
|
||||
The tests cover:
|
||||
- URL construction validation
|
||||
- Response parsing for new API format
|
||||
- Error handling scenarios
|
||||
- Configuration validation
|
||||
- Successful API responses
|
||||
- HTTP error handling
|
||||
- Network failures
|
||||
- Invalid JSON responses
|
||||
- Missing required fields
|
||||
- Plugin provider functionality
|
||||
|
||||
## Migration Notes
|
||||
|
||||
This plugin replaces direct DeDi API integration with the new DeDi Wrapper API format:
|
||||
|
||||
- **Removed**: API key authentication, namespaceID parameters
|
||||
- **Added**: Configurable registryName parameter
|
||||
- **Changed**: POST requests → GET requests
|
||||
- **Updated**: Response structure parsing (`data.details` object)
|
||||
- **Added**: New URL path parameter format
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -165,19 +145,8 @@ Test coverage includes:
|
||||
|
||||
## Error Handling
|
||||
|
||||
- **Configuration Errors**: Missing required config parameters
|
||||
- **Configuration Errors**: Missing url or registryName
|
||||
- **Network Errors**: Connection failures, timeouts
|
||||
- **HTTP Errors**: Non-200 status codes from DeDi API
|
||||
- **HTTP Errors**: Non-200 status codes from DeDi wrapper
|
||||
- **Data Errors**: Missing required fields in response
|
||||
- **Validation Errors**: Empty subscriber ID in request
|
||||
|
||||
|
||||
### Integration Notes
|
||||
|
||||
- **Plugin Type**: Registry implementation
|
||||
- **Interface**: Implements `RegistryLookup` interface with `Lookup(ctx, *model.Subscription) ([]model.Subscription, error)`
|
||||
- **Manager Access**: Available via `manager.Registry()` method (same as standard registry)
|
||||
- **Dynamic Lookup**: Uses `req.SubscriberID` from request context, not static configuration
|
||||
- **Data Conversion**: Automatically converts DeDi API format to Beckn Subscription format
|
||||
- **Build Integration**: Included in `build-plugins.sh`, compiles to `dediregistry.so`
|
||||
- **Usage Pattern**: Configure with `id: dediregistry` in registry plugin configuration
|
||||
- **Validation Errors**: Empty subscriber ID or key ID in request
|
||||
Reference in New Issue
Block a user