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
This commit is contained in:
1 parent
bb6b320d1f
commit
a1800227a7
11 files changed
+876
-138
No files matched your search
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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, "");
|
||||
}
|
||||
Reference in new issue
Block a user