mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 15:30:56 +00:00
106 lines
3.5 KiB
TypeScript
106 lines
3.5 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Get,
|
|
HttpCode,
|
|
HttpStatus,
|
|
Post,
|
|
Query,
|
|
Req,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import {
|
|
ApiBearerAuth,
|
|
ApiOkResponse,
|
|
ApiOperation,
|
|
ApiTags,
|
|
} from '@nestjs/swagger';
|
|
import { Throttle } from '@nestjs/throttler';
|
|
import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/current-user.type';
|
|
import { JwtGuard } from '../../common/jwt.guard';
|
|
import { OptionalJwtGuard } from './optional-jwt.guard';
|
|
import {
|
|
CompleteVerificationResultDto,
|
|
StartVerificationDto,
|
|
VerifaydaCallbackDto,
|
|
VerificationStatusDto,
|
|
} from './verifayda.dto';
|
|
import { VerifaydaService } from './verifayda.service';
|
|
|
|
/** Minimal slices of the Express req we touch (avoids a hard dependency on
|
|
* `@types/express`, which isn't resolved in this package). */
|
|
interface RequestWithOptionalUser {
|
|
user?: TCurrentUser;
|
|
}
|
|
interface RequestWithUser {
|
|
user: TCurrentUser;
|
|
}
|
|
|
|
@ApiTags('Fayda Verification')
|
|
@Controller('fayda/verification')
|
|
@Throttle({ auth: { limit: 5, ttl: 60_000 } })
|
|
export class VerifaydaController {
|
|
constructor(private readonly service: VerifaydaService) {}
|
|
|
|
@Post('start')
|
|
@HttpCode(HttpStatus.OK)
|
|
@UseGuards(OptionalJwtGuard)
|
|
@ApiBearerAuth('JWT-auth')
|
|
@ApiOperation({
|
|
summary: 'Start a VeriFayda 2.0 verification session',
|
|
description: `Creates a verification session and returns the eSignet authorize URL the frontend should send the user to.
|
|
|
|
- Works for **logged-in users** and **guests**. If a valid bearer token is present, the verification is tied to that user.
|
|
- **VERIFY** (default): the user proves their identity and \`/complete\` returns the verified attributes (name, email, phone, dob, gender).
|
|
- **LOGIN**: \`/complete\` resolves/creates the user and returns a JWT.
|
|
- The returned \`authorizationUrl\` already carries the PKCE \`code_challenge\`, CSRF \`state\`, requested \`claims\`, and \`code_challenge_method=S256\`. The frontend simply navigates to it (full page or popup).`,
|
|
})
|
|
@ApiOkResponse({
|
|
description: 'Authorize URL the frontend should redirect the user to.',
|
|
schema: {
|
|
example: {
|
|
authorizationUrl:
|
|
'https://esignet.example.com/authorize?client_id=...&state=...&code_challenge=...',
|
|
},
|
|
},
|
|
})
|
|
async start(
|
|
@Body() dto: StartVerificationDto,
|
|
@Req() req: RequestWithOptionalUser,
|
|
): Promise<{ authorizationUrl: string }> {
|
|
const authorizationUrl = await this.service.startVerification({
|
|
purpose: dto.purpose ?? 'VERIFY',
|
|
platform: dto.platform ?? 'WEB',
|
|
userId: req.user?.id,
|
|
});
|
|
return { authorizationUrl };
|
|
}
|
|
|
|
@Get('complete')
|
|
@ApiOperation({
|
|
summary: 'Complete a verification (Fayda redirect / client callback lands here)',
|
|
description: `This is the registered Fayda \`redirect_uri\`. Fayda redirects the browser here with \`?code&state\``,
|
|
})
|
|
@ApiOkResponse({ type: CompleteVerificationResultDto })
|
|
async complete(
|
|
@Query() dto: VerifaydaCallbackDto,
|
|
): Promise<CompleteVerificationResultDto> {
|
|
return this.service.completeVerification(dto);
|
|
}
|
|
|
|
@Get('status')
|
|
@UseGuards(JwtGuard)
|
|
@ApiBearerAuth('JWT-auth')
|
|
@ApiOperation({
|
|
summary: "Get the current user's Fayda verification status",
|
|
description:
|
|
'Returns whether the authenticated user has linked a verified Fayda identity to their account, when, and the name on file.',
|
|
})
|
|
@ApiOkResponse({ type: VerificationStatusDto })
|
|
async status(
|
|
@Req() req: RequestWithUser,
|
|
): Promise<VerificationStatusDto> {
|
|
return this.service.getVerificationStatus(req.user.id);
|
|
}
|
|
}
|