Files
pagodera/lib/validators/document-validator.ts
T
Evandro Fonseca Junior a1800227a7 refactor(api): enhance donation creation with rate limiting, Zod validation, and secure logging
- Add rate limiting to prevent abuse on /api/donations/create endpoint
- Replace manual input validation with Zod schema for better error handling and type safety
- Switch from console.log to secureLogger to comply with LGPD and avoid exposing sensitive data
- Remove sensitive request body logging in AbacatePay client for improved security
2025-10-26 23:01:19 -03:00

86 lines
2.5 KiB
TypeScript

/**
* Validador de documentos brasileiros (CPF e CNPJ)
* Implementa algoritmo completo de validação de dígitos verificadores
*/
export function isValidCPF(cpf: string): boolean {
// Remove caracteres não numéricos
const cleaned = cpf.replace(/[^\d]/g, "");
// Verifica se tem 11 dígitos
if (cleaned.length !== 11) return false;
// Verifica se todos os dígitos são iguais (ex: 111.111.111-11)
if (/^(\d)\1+$/.test(cleaned)) return false;
// Valida primeiro dígito verificador
let sum = 0;
for (let i = 0; i < 9; i++) {
sum += parseInt(cleaned.charAt(i)) * (10 - i);
}
let remainder = (sum * 10) % 11;
if (remainder === 10 || remainder === 11) remainder = 0;
if (remainder !== parseInt(cleaned.charAt(9))) return false;
// Valida segundo dígito verificador
sum = 0;
for (let i = 0; i < 10; i++) {
sum += parseInt(cleaned.charAt(i)) * (11 - i);
}
remainder = (sum * 10) % 11;
if (remainder === 10 || remainder === 11) remainder = 0;
if (remainder !== parseInt(cleaned.charAt(10))) return false;
return true;
}
export function isValidCNPJ(cnpj: string): boolean {
// Remove caracteres não numéricos
const cleaned = cnpj.replace(/[^\d]/g, "");
// Verifica se tem 14 dígitos
if (cleaned.length !== 14) return false;
// Verifica se todos os dígitos são iguais
if (/^(\d)\1+$/.test(cleaned)) return false;
// Valida primeiro dígito verificador
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
let sum = 0;
for (let i = 0; i < 12; i++) {
sum += parseInt(cleaned.charAt(i)) * weights1[i];
}
let remainder = sum % 11;
const firstDigit = remainder < 2 ? 0 : 11 - remainder;
if (firstDigit !== parseInt(cleaned.charAt(12))) return false;
// Valida segundo dígito verificador
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
sum = 0;
for (let i = 0; i < 13; i++) {
sum += parseInt(cleaned.charAt(i)) * weights2[i];
}
remainder = sum % 11;
const secondDigit = remainder < 2 ? 0 : 11 - remainder;
if (secondDigit !== parseInt(cleaned.charAt(13))) return false;
return true;
}
export function isValidDocument(document: string): boolean {
const cleaned = document.replace(/[^\d]/g, "");
if (cleaned.length === 11) {
return isValidCPF(document);
} else if (cleaned.length === 14) {
return isValidCNPJ(document);
}
return false;
}
export function normalizeDocument(document: string): string {
// Remove todos os caracteres não numéricos
return document.replace(/[^\d]/g, "");
}