feat: add callAsService for service-to-service auth
- Add CoreService.callAsService(pluginId, path, body) method - Signs requests with HMAC-SHA256 using REGISTRATION_KEY - Sends X-Service-Auth header for service-to-service authentication
This commit is contained in:
parent
b4d214d9c3
commit
3451a23e8e
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@erp/plugin-sdk",
|
||||
"version": "1.10.1",
|
||||
"version": "1.10.2",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"bin": {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { ClientProxy } from '@nestjs/microservices';
|
|||
import { firstValueFrom, timeout as rxTimeout } from 'rxjs';
|
||||
import { SystemEvent } from '../interfaces/communication';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as amqp from 'amqplib';
|
||||
|
|
@ -167,6 +168,35 @@ export class CoreService {
|
|||
});
|
||||
}
|
||||
|
||||
async callAsService<T = any>(pluginId: string, path: string, body?: any): Promise<T> {
|
||||
const registrationKey = process.env.REGISTRATION_KEY || '';
|
||||
if (!registrationKey) {
|
||||
throw new Error('REGISTRATION_KEY not configured — cannot make service-to-service call');
|
||||
}
|
||||
const payload = JSON.stringify({
|
||||
pluginId,
|
||||
path: path.replace(/^\//, ''),
|
||||
timestamp: Date.now(),
|
||||
body: body !== undefined ? body : null,
|
||||
});
|
||||
const signature = crypto.createHmac('sha256', registrationKey).update(payload).digest('hex');
|
||||
const encoded = Buffer.from(payload).toString('base64');
|
||||
const serviceAuth = `v1.${encoded}.${signature}`;
|
||||
|
||||
const coreUrl = process.env.CORE_BACKEND_URL || 'http://localhost:3001';
|
||||
const response = await fetch(`${coreUrl}/api/plugins/rpc/${pluginId}/${path.replace(/^\//, '')}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-Service-Auth': serviceAuth },
|
||||
body: body !== undefined ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const text = await response.text().catch(() => response.statusText);
|
||||
throw new Error(`Service call to ${pluginId}/${path} failed: ${response.status} ${text}`);
|
||||
}
|
||||
const text = await response.text();
|
||||
try { return JSON.parse(text); } catch { return text as any; }
|
||||
}
|
||||
|
||||
async discoverPlugins(): Promise<any[]> {
|
||||
try {
|
||||
const response = await this.fetchCore('/api/plugins/discovery');
|
||||
|
|
|
|||
Loading…
Reference in New Issue