From 09b2bdb28905f205d979ce08e3dccfa544ba60fc Mon Sep 17 00:00:00 2001 From: abdulrcrtw Date: Tue, 2 Jun 2026 12:57:37 +0100 Subject: [PATCH] feat: add public verification endpoint --- backend/src/app.module.ts | 2 + .../public-verification.controller.ts | 32 +++++++++++ .../public-verification.module.ts | 25 ++++++++ .../public-verification.service.ts | 57 +++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 backend/src/module/public-verification/public-verification.controller.ts create mode 100644 backend/src/module/public-verification/public-verification.module.ts create mode 100644 backend/src/module/public-verification/public-verification.service.ts diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 49cbfd6..a389d88 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -12,6 +12,7 @@ import { DocumentsModule } from './documents/documents.module'; import { MailModule } from './mail/mail.module'; import { QueueModule } from './queue/queue.module'; import { RiskAssessmentModule } from './risk-assessment/risk-assessment.module'; +import { PublicVerificationModule } from './module/public-verification/public-verification.module'; import { StellarModule } from './stellar/stellar.module'; import { UsersModule } from './users/users.module'; import { VerificationModule } from './verification/verification.module'; @@ -51,6 +52,7 @@ import { ConfigValidationSchema } from './config/config.validation'; UsersModule, AuthModule, DocumentsModule, + PublicVerificationModule, RiskAssessmentModule, StellarModule, VerificationModule, diff --git a/backend/src/module/public-verification/public-verification.controller.ts b/backend/src/module/public-verification/public-verification.controller.ts new file mode 100644 index 0000000..ef18998 --- /dev/null +++ b/backend/src/module/public-verification/public-verification.controller.ts @@ -0,0 +1,32 @@ +import { + BadRequestException, + Controller, + Get, + Param, + UseGuards, +} from '@nestjs/common'; +import { Throttle, ThrottlerGuard } from '@nestjs/throttler'; + +import { PublicVerificationService } from './public-verification.service'; + +@Controller('module') +@UseGuards(ThrottlerGuard) +export class PublicVerificationController { + constructor( + private readonly publicVerificationService: PublicVerificationService, + ) {} + + @Get('verify/:hash') + @Throttle({ default: { limit: 30, ttl: 60_000 } }) + async verify(@Param('hash') hash: string) { + const normalizedHash = hash.trim().toLowerCase(); + + if (!/^[a-f0-9]{64}$/.test(normalizedHash)) { + throw new BadRequestException( + 'Hash must be a 64-character hexadecimal string', + ); + } + + return this.publicVerificationService.verifyHash(normalizedHash); + } +} diff --git a/backend/src/module/public-verification/public-verification.module.ts b/backend/src/module/public-verification/public-verification.module.ts new file mode 100644 index 0000000..f12d410 --- /dev/null +++ b/backend/src/module/public-verification/public-verification.module.ts @@ -0,0 +1,25 @@ +import { Module } from '@nestjs/common'; +import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler'; + +import { DocumentsModule } from '../../documents/documents.module'; +import { StellarModule } from '../../stellar/stellar.module'; +import { VerificationModule } from '../../verification/verification.module'; +import { PublicVerificationController } from './public-verification.controller'; +import { PublicVerificationService } from './public-verification.service'; + +@Module({ + imports: [ + DocumentsModule, + StellarModule, + VerificationModule, + ThrottlerModule.forRoot([ + { + limit: 30, + ttl: 60_000, + }, + ]), + ], + controllers: [PublicVerificationController], + providers: [PublicVerificationService, ThrottlerGuard], +}) +export class PublicVerificationModule {} diff --git a/backend/src/module/public-verification/public-verification.service.ts b/backend/src/module/public-verification/public-verification.service.ts new file mode 100644 index 0000000..d84b51d --- /dev/null +++ b/backend/src/module/public-verification/public-verification.service.ts @@ -0,0 +1,57 @@ +import { Injectable } from '@nestjs/common'; + +import { DocumentsService } from '../../documents/documents.service'; +import { StellarService } from '../../stellar/stellar.service'; +import { VerificationService } from '../../verification/verification.service'; + +export interface PublicVerificationResult { + verified: boolean; + txHash: string | null; + ledger: number | null; + anchoredAt: Date | null; +} + +@Injectable() +export class PublicVerificationService { + constructor( + private readonly documentsService: DocumentsService, + private readonly verificationService: VerificationService, + private readonly stellarService: StellarService, + ) {} + + async verifyHash(hash: string): Promise { + const verifiedOnStellar = await this.stellarService.verifyHash(hash); + + if (!verifiedOnStellar) { + return this.createEmptyResponse(); + } + + const document = await this.documentsService.findByFileHash(hash); + if (!document) { + return this.createEmptyResponse(true); + } + + const latestVerification = + await this.verificationService.findLatestByDocument(document.id); + + if (!latestVerification) { + return this.createEmptyResponse(true); + } + + return { + verified: true, + txHash: latestVerification.stellarTxHash, + ledger: latestVerification.stellarLedger, + anchoredAt: latestVerification.anchoredAt ?? null, + }; + } + + private createEmptyResponse(verified = false): PublicVerificationResult { + return { + verified, + txHash: null, + ledger: null, + anchoredAt: null, + }; + } +}