Enhance WHMCS integration with mTLS support and product mapping features. Added mTLS configuration options, updated API endpoints for mTLS status and fingerprint registration, and implemented product validation API. Updated database schema and documentation accordingly.
This commit is contained in:
93
apps/api/src/integrations/whmcs/whmcs-mtls.service.ts
Normal file
93
apps/api/src/integrations/whmcs/whmcs-mtls.service.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import type { WhmcsRegisterMtlsRequest } from '@hexahost/contracts';
|
||||
import { normalizeCertificateFingerprint } from '@hexahost/integration-auth';
|
||||
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
|
||||
type InstallationRef = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class WhmcsMtlsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async registerFingerprint(
|
||||
installation: InstallationRef,
|
||||
input: WhmcsRegisterMtlsRequest,
|
||||
idempotencyKey: string,
|
||||
): Promise<{
|
||||
integrationId: string;
|
||||
fingerprint: string | null;
|
||||
subject: string | null;
|
||||
registered: boolean;
|
||||
}> {
|
||||
const existingOp = await this.prisma.integrationOperation.findUnique({
|
||||
where: { idempotencyKey },
|
||||
});
|
||||
if (existingOp?.result) {
|
||||
return existingOp.result as {
|
||||
integrationId: string;
|
||||
fingerprint: string | null;
|
||||
subject: string | null;
|
||||
registered: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
const fingerprint = normalizeCertificateFingerprint(input.fingerprint);
|
||||
|
||||
const updated = await this.prisma.whmcsInstallation.update({
|
||||
where: { id: installation.id },
|
||||
data: {
|
||||
mtlsClientFingerprint: fingerprint,
|
||||
mtlsClientSubject: input.subject ?? null,
|
||||
},
|
||||
select: {
|
||||
integrationId: true,
|
||||
mtlsClientFingerprint: true,
|
||||
mtlsClientSubject: true,
|
||||
},
|
||||
});
|
||||
|
||||
const result = {
|
||||
integrationId: updated.integrationId,
|
||||
fingerprint: updated.mtlsClientFingerprint,
|
||||
subject: updated.mtlsClientSubject,
|
||||
registered: true,
|
||||
};
|
||||
|
||||
await this.prisma.integrationOperation.create({
|
||||
data: {
|
||||
installationId: installation.id,
|
||||
idempotencyKey,
|
||||
operation: 'mtls:register',
|
||||
status: 'COMPLETED',
|
||||
result: result as object,
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async getMtlsStatus(installation: InstallationRef) {
|
||||
const row = await this.prisma.whmcsInstallation.findUniqueOrThrow({
|
||||
where: { id: installation.id },
|
||||
select: {
|
||||
integrationId: true,
|
||||
mtlsClientFingerprint: true,
|
||||
mtlsClientSubject: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
integrationId: row.integrationId,
|
||||
mtlsEnabled: process.env['INTEGRATION_MTLS_ENABLED'] === 'true',
|
||||
fingerprintRegistered: Boolean(row.mtlsClientFingerprint),
|
||||
fingerprintPreview: row.mtlsClientFingerprint
|
||||
? `${row.mtlsClientFingerprint.slice(0, 8)}…${row.mtlsClientFingerprint.slice(-8)}`
|
||||
: null,
|
||||
subject: row.mtlsClientSubject,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user