feat: Implement password masking and encryption in data services
- Added a new function `maskPasswordColumns` to mask password fields in data responses, ensuring sensitive information is not exposed. - Integrated password handling in `DynamicFormService` to encrypt new passwords and maintain existing ones when empty values are provided. - Enhanced logging for better tracking of password field updates and masking failures, improving overall security and debugging capabilities.
This commit is contained in:
@@ -596,10 +596,22 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
||||
const additionalFields = componentConfig.additionalFields || [];
|
||||
const mainTable = componentConfig.targetTable!;
|
||||
|
||||
// 수정 모드 감지: URL에 mode=edit가 있으면 수정 모드
|
||||
// 수정 모드 감지 (2가지 방법으로 확인)
|
||||
// 1. URL에 mode=edit 파라미터 확인
|
||||
// 2. 로드된 데이터에 DB id(PK)가 존재하는지 확인
|
||||
// 수정 모드에서는 항상 deleteOrphans=true (기존 레코드 교체, 복제 방지)
|
||||
const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
|
||||
const isEditMode = urlParams?.get("mode") === "edit";
|
||||
const urlEditMode = urlParams?.get("mode") === "edit";
|
||||
const dataHasDbId = items.some(item => !!item.originalData?.id);
|
||||
const isEditMode = urlEditMode || dataHasDbId;
|
||||
|
||||
console.log("[SelectedItemsDetailInput] 수정 모드 감지:", {
|
||||
urlEditMode,
|
||||
dataHasDbId,
|
||||
isEditMode,
|
||||
itemCount: items.length,
|
||||
firstItemId: items[0]?.originalData?.id,
|
||||
});
|
||||
|
||||
// fieldGroup별 sourceTable 분류
|
||||
const groupsByTable = new Map<string, typeof groups>();
|
||||
@@ -695,6 +707,16 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
||||
// 신규 등록이고 id 없으면 → 기존 레코드 건드리지 않음
|
||||
const mappingHasDbIds = mappingRecords.some((r) => !!r.id);
|
||||
const shouldDeleteOrphans = isEditMode || mappingHasDbIds;
|
||||
|
||||
console.log(`[SelectedItemsDetailInput] ${mainTable} 저장:`, {
|
||||
isEditMode,
|
||||
mappingHasDbIds,
|
||||
shouldDeleteOrphans,
|
||||
recordCount: mappingRecords.length,
|
||||
recordIds: mappingRecords.map(r => r.id || "NEW"),
|
||||
parentKeys: itemParentKeys,
|
||||
});
|
||||
|
||||
// 저장된 매핑 ID를 추적 (디테일 테이블에 mapping_id 주입용)
|
||||
let savedMappingIds: string[] = [];
|
||||
try {
|
||||
@@ -782,6 +804,16 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
||||
|
||||
const priceHasDbIds = priceRecords.some((r) => !!r.id);
|
||||
const shouldDeleteDetailOrphans = isEditMode || priceHasDbIds;
|
||||
|
||||
console.log(`[SelectedItemsDetailInput] ${detailTable} 저장:`, {
|
||||
isEditMode,
|
||||
priceHasDbIds,
|
||||
shouldDeleteDetailOrphans,
|
||||
recordCount: priceRecords.length,
|
||||
recordIds: priceRecords.map(r => r.id || "NEW"),
|
||||
parentKeys: itemParentKeys,
|
||||
});
|
||||
|
||||
try {
|
||||
const detailResult = await dataApi.upsertGroupedRecords(
|
||||
detailTable,
|
||||
|
||||
Reference in New Issue
Block a user