feat: done app layer for external use

This commit is contained in:
yosaphatprs 2025-11-13 16:18:29 +07:00
parent fac4a791c4
commit 9f6d861ea0
6 changed files with 109 additions and 16 deletions

View File

@ -34,8 +34,7 @@ export class StoreLogDto {
event: string; event: string;
@IsNotEmpty({ message: 'User ID wajib diisi' }) @IsNotEmpty({ message: 'User ID wajib diisi' })
@IsNumber({}, { message: 'User ID harus berupa angka' }) user_id: number | string;
user_id: number;
@IsNotEmpty({ message: 'Payload wajib diisi' }) @IsNotEmpty({ message: 'Payload wajib diisi' })
@IsString({ message: 'Payload harus berupa string' }) @IsString({ message: 'Payload harus berupa string' })

View File

@ -0,0 +1,36 @@
import {
ArrayMaxSize,
ArrayMinSize,
IsArray,
IsBoolean,
IsDate,
isDateString,
IsIn,
IsNotEmpty,
IsObject,
IsOptional,
IsString,
Length,
Matches,
ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';
export class LogProofDto {
@IsNotEmpty({ message: 'Proof wajib diisi' })
@IsObject({ message: 'Proof harus berupa objek' })
proofHash: object;
@IsNotEmpty({ message: 'ID Visit wajib diisi' })
@IsString({ message: 'ID Visit harus berupa string' })
@Length(1, 25, { message: 'ID Visit maksimal 25 karakter' })
id_visit: string;
@IsNotEmpty({ message: 'Hasil proof wajib diisi' })
@IsBoolean({ message: 'Hasil proof harus berupa boolean' })
proofResult: boolean;
@IsNotEmpty({ message: 'Timestamp wajib diisi' })
@IsString({ message: 'Timestamp harus berupa string' })
timestamp: Date;
}

View File

@ -0,0 +1,8 @@
import { IsNotEmpty, IsString, Length } from 'class-validator';
export class RequestProofDto {
@IsNotEmpty({ message: 'ID Visit wajib diisi' })
@IsString({ message: 'ID Visit harus berupa string' })
@Length(1, 25, { message: 'ID Visit maksimal 25 karakter' })
id_visit: string;
}

View File

@ -1,12 +1,19 @@
import { Body, Controller, Post, UseGuards } from '@nestjs/common'; import { Body, Controller, Post, UseGuards } from '@nestjs/common';
import { ProofService } from './proof.service'; import { ProofService } from './proof.service';
import { RequestProofDto } from './dto/request-proof.dto';
import { LogProofDto } from './dto/log-proof.dto';
@Controller('proof') @Controller('proof')
export class ProofController { export class ProofController {
constructor(private proofService: ProofService) {} constructor(private proofService: ProofService) {}
@Post('/request') @Post('/request')
requestProof(@Body('id_visit') id_visit: string) { requestProof(@Body() requestProofDto: RequestProofDto) {
return this.proofService.getProof(id_visit); return this.proofService.getProof(requestProofDto);
}
@Post('/log-verification')
logVerification(@Body() logProofDto: LogProofDto) {
return this.proofService.logVerificationProof(logProofDto);
} }
} }

View File

@ -3,9 +3,10 @@ import { ProofController } from './proof.controller';
import { ProofService } from './proof.service'; import { ProofService } from './proof.service';
import { RekamMedisModule } from '../rekammedis/rekammedis.module'; import { RekamMedisModule } from '../rekammedis/rekammedis.module';
import { PrismaModule } from '../prisma/prisma.module'; import { PrismaModule } from '../prisma/prisma.module';
import { LogModule } from '../log/log.module';
@Module({ @Module({
imports: [RekamMedisModule, PrismaModule], imports: [RekamMedisModule, PrismaModule, LogModule],
providers: [ProofService], providers: [ProofService],
controllers: [ProofController], controllers: [ProofController],
}) })

View File

@ -7,12 +7,17 @@ import { PrismaService } from '../prisma/prisma.service';
import { RekammedisService } from '../rekammedis/rekammedis.service'; import { RekammedisService } from '../rekammedis/rekammedis.service';
import { groth16, wtns } from 'snarkjs'; import { groth16, wtns } from 'snarkjs';
import path from 'path'; import path from 'path';
import { RequestProofDto } from './dto/request-proof.dto';
import { LogProofDto } from './dto/log-proof.dto';
import { sha256 } from '@api/common/crypto/hash';
import { LogService } from '../log/log.service';
@Injectable() @Injectable()
export class ProofService { export class ProofService {
constructor( constructor(
private prismaService: PrismaService, private prismaService: PrismaService,
private rekamMedisService: RekammedisService, private rekamMedisService: RekammedisService,
private logService: LogService,
) {} ) {}
buildDir = path.join(__dirname, '../../../', 'dist'); buildDir = path.join(__dirname, '../../../', 'dist');
@ -38,26 +43,63 @@ export class ProofService {
return { proof, publicSignals }; return { proof, publicSignals };
} }
async getProof(id_visit: any) { async getProof(requestProofDto: RequestProofDto) {
const age = await this.rekamMedisService.getAgeByIdVisit(id_visit); const age = await this.rekamMedisService.getAgeByIdVisit(
requestProofDto.id_visit,
);
if (!age) { if (!age) {
throw new NotFoundException('ID Visit tidak ditemukan'); throw new NotFoundException('ID Visit tidak ditemukan');
} }
try { // try {
await this.calculateWitness(age); // await this.calculateWitness(age);
} catch (error) { // } catch (error) {
console.log('Error during witness calculation:', error); // console.log('Error during witness calculation:', error);
throw new InternalServerErrorException( // throw new InternalServerErrorException(
"Can't generate proof from input based on constraint. Please check the input data and try again.", // "Can't generate proof from input based on constraint. Please check the input data and try again.",
); // );
} // }
const { proof, publicSignals } = await this.generateProof(); // const { proof, publicSignals } = await this.generateProof();
const { proof, publicSignals } = await groth16.fullProve(
{
age: age,
threshold: 18,
},
this.wasmPath,
this.zkeyPath,
);
return { return {
proof: proof, proof: proof,
publicSignals: publicSignals, publicSignals: publicSignals,
}; };
} }
async logVerificationProof(logProofDto: LogProofDto) {
const payload = {
id_visit: logProofDto.id_visit || null,
proofHash: logProofDto.proofHash || null,
proofResult: logProofDto.proofResult || null,
};
const payloadHash = sha256(JSON.stringify(payload));
const response = {
id: `PROOF_${payload.id_visit}`,
event: 'proof_verification_logged',
user_id: 'External',
payload: payloadHash,
};
// const response = await this.logService.storeLog({
// id: `PROOF_${payload.id_visit}`,
// event: 'proof_verification_logged',
// user_id: 'External',
// payload: payloadHash,
// });
return response;
}
} }