You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.6 KiB
62 lines
1.6 KiB
import {
|
|
DEFAULT_MASK_FIELD_KEYWORDS,
|
|
NEVER_EXPORT_FIELD_EXACT_NAMES,
|
|
type ExportMaskPolicy,
|
|
} from "../constants/export";
|
|
|
|
function hitKeyword(field: string, keywords: readonly string[]): boolean {
|
|
const name = field.toLowerCase();
|
|
return keywords.some((k) => name.includes(k.toLowerCase()));
|
|
}
|
|
|
|
function normalizeFieldName(field: string): string {
|
|
return field.toLowerCase().replace(/[_-]/g, "");
|
|
}
|
|
|
|
function shouldNeverExportField(field: string): boolean {
|
|
const normalizedField = normalizeFieldName(field);
|
|
return NEVER_EXPORT_FIELD_EXACT_NAMES.includes(
|
|
normalizedField as (typeof NEVER_EXPORT_FIELD_EXACT_NAMES)[number],
|
|
);
|
|
}
|
|
|
|
function shouldMaskField(field: string): boolean {
|
|
return hitKeyword(field, DEFAULT_MASK_FIELD_KEYWORDS);
|
|
}
|
|
|
|
function maskValue(value: unknown): unknown {
|
|
if (value === null || value === undefined) {
|
|
return value;
|
|
}
|
|
if (typeof value === "string") {
|
|
return "***";
|
|
}
|
|
if (typeof value === "number") {
|
|
return 0;
|
|
}
|
|
if (typeof value === "boolean") {
|
|
return false;
|
|
}
|
|
return "[masked]";
|
|
}
|
|
|
|
export function sanitizeUserForExport(
|
|
row: Record<string, unknown>,
|
|
maskPolicy: ExportMaskPolicy,
|
|
): Record<string, unknown> {
|
|
const out: Record<string, unknown> = {};
|
|
for (const [field, value] of Object.entries(row)) {
|
|
if (shouldNeverExportField(field)) {
|
|
continue;
|
|
}
|
|
if (maskPolicy === "masked" && shouldMaskField(field)) {
|
|
out[field] = maskValue(value);
|
|
continue;
|
|
}
|
|
out[field] = value;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// Backward-compatible alias used by current tests/callers.
|
|
export const applyExportMask = sanitizeUserForExport;
|
|
|