feat(signatures): UI completa do módulo + rate limiting em rotas públicas
Fecha as duas pendências da leva anterior (módulo de Assinatura Eletrônica): tela de backoffice para gerenciar envelopes (criação, envio, cancelamento, checkpoint/finalização, auditoria) e as duas páginas públicas (/assinar/:token, /verificar/:verificationId). Backend: novos endpoints de streaming de PDF (documento congelado e PDF final consolidado, autenticados e via token público) que faltavam para a UI funcionar — o signatário não tinha como ver o próprio documento antes de confirmar leitura. Rate limiting (guard próprio, em memória, chaves por IP e por token) em todas as rotas sem sessão: auth (login/mfa/forgot-password/reset-password/refresh/logout) e todo o fluxo público de assinatura/verificação. Suíte: 77/77 verdes. pnpm turbo run typecheck build: 28/28. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
76
apps/core-web/src/lib/api/public-signature.ts
Normal file
76
apps/core-web/src/lib/api/public-signature.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Client for `apps/api` `/v1/public-signature/:token/*` — the signer-facing
|
||||
* flow reached via the emailed link `/assinar/:token` (see
|
||||
* apps/api/src/signatures/public-signature.controller.ts +
|
||||
* public-signature.service.ts for the source of truth). Deliberately NOT
|
||||
* authenticated: the token in the URL is the entire authorization,
|
||||
* there's never an `accessToken` header here — mirrored by never taking
|
||||
* one as a parameter in this file, unlike `./signatures.ts`.
|
||||
*/
|
||||
import { API_BASE_URL, apiRequest } from "./http.js";
|
||||
import type { PartyRole, PersonType, SignerStatus } from "./signatures.js";
|
||||
|
||||
export interface PublicSignerState {
|
||||
id: string;
|
||||
party: PartyRole;
|
||||
person_type: PersonType | null;
|
||||
full_name: string;
|
||||
cpf: string | null;
|
||||
email: string;
|
||||
phone: string | null;
|
||||
company_name: string | null;
|
||||
cnpj: string | null;
|
||||
role_title: string | null;
|
||||
status: SignerStatus;
|
||||
documentsRead: string[];
|
||||
}
|
||||
|
||||
export interface PublicDocumentState {
|
||||
id: string;
|
||||
title: string;
|
||||
documentVersion: number;
|
||||
pageCount: number | null;
|
||||
confirmedRead: boolean;
|
||||
}
|
||||
|
||||
export interface PublicSignatureState {
|
||||
envelope: { id: string; envelopeNumber: string; status: string };
|
||||
signer: PublicSignerState;
|
||||
documents: PublicDocumentState[];
|
||||
}
|
||||
|
||||
export function getPublicSignatureState(token: string): Promise<PublicSignatureState> {
|
||||
return apiRequest<PublicSignatureState>(`/public-signature/${token}`, { method: "GET" });
|
||||
}
|
||||
|
||||
/** Opens the document's PDF in a new tab — no bearer token needed, the token is already in the path, so a plain `window.open` works (unlike the authenticated backoffice equivalent in `./signatures.ts`). */
|
||||
export function publicDocumentPdfUrl(token: string, documentId: string): string {
|
||||
return `${API_BASE_URL}/public-signature/${token}/documents/${documentId}/pdf`;
|
||||
}
|
||||
|
||||
export function confirmDocumentRead(token: string, documentId: string): Promise<void> {
|
||||
return apiRequest<void>(`/public-signature/${token}/documents/${documentId}/confirm-read`, { method: "POST" });
|
||||
}
|
||||
|
||||
export function confirmSignerData(token: string): Promise<void> {
|
||||
return apiRequest<void>(`/public-signature/${token}/confirm-data`, { method: "POST" });
|
||||
}
|
||||
|
||||
export function acceptConsent(token: string): Promise<void> {
|
||||
return apiRequest<void>(`/public-signature/${token}/consent`, { method: "POST" });
|
||||
}
|
||||
|
||||
export function requestOtp(token: string): Promise<void> {
|
||||
return apiRequest<void>(`/public-signature/${token}/otp/request`, { method: "POST" });
|
||||
}
|
||||
|
||||
export function verifyOtp(token: string, code: string): Promise<void> {
|
||||
return apiRequest<void>(`/public-signature/${token}/otp/verify`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ code }),
|
||||
});
|
||||
}
|
||||
|
||||
export function commitSignature(token: string): Promise<void> {
|
||||
return apiRequest<void>(`/public-signature/${token}/sign`, { method: "POST" });
|
||||
}
|
||||
Reference in New Issue
Block a user