feat: Implement company code validation in flow management

- Enhanced the FlowController to include user company code validation for flow definitions, ensuring that users can only access and modify flows belonging to their company.
- Updated the FlowDefinitionService to accept company code as a parameter for create, update, and delete operations, enforcing ownership checks.
- Introduced sanitization methods in FlowConditionParser to prevent SQL injection for column and table names.
- Modified the FlowDataMoveService to validate table names and column names during data movement operations, enhancing security.
- Updated the frontend components to support batch data movement with proper validation and error handling.
This commit is contained in:
kjs
2026-03-03 10:38:38 +09:00
parent e2d88f01e3
commit fd5c61b12a
9 changed files with 207 additions and 56 deletions
+22 -9
View File
@@ -7,7 +7,7 @@ import { Badge } from "@/components/ui/badge";
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { Loader2, AlertCircle, ArrowRight } from "lucide-react";
import { getStepDataList, moveDataToNextStep } from "@/lib/api/flow";
import { getStepDataList, moveBatchData, getFlowConnections } from "@/lib/api/flow";
import { toast } from "sonner";
interface FlowDataListModalProps {
@@ -102,15 +102,28 @@ export function FlowDataListModal({
try {
setMovingData(true);
// 선택된 행의 ID 추출 (가정: 각 행에 'id' 필드가 있음)
const selectedDataIds = Array.from(selectedRows).map((index) => data[index].id);
// 다음 스텝 결정 (연결 정보에서 조회)
const connResponse = await getFlowConnections(flowId);
if (!connResponse.success || !connResponse.data) {
throw new Error("플로우 연결 정보를 가져올 수 없습니다");
}
const nextConn = connResponse.data.find((c: any) => c.fromStepId === stepId);
if (!nextConn) {
throw new Error("다음 단계가 연결되어 있지 않습니다");
}
// 데이터 이동 API 호
for (const dataId of selectedDataIds) {
const response = await moveDataToNextStep(flowId, stepId, dataId);
if (!response.success) {
throw new Error(`데이터 이동 실패: ${response.message}`);
}
// 선택된 행의 ID 추
const selectedDataIds = Array.from(selectedRows).map((index) => String(data[index].id));
// 배치 이동 API 호출
const response = await moveBatchData({
flowId,
fromStepId: stepId,
toStepId: nextConn.toStepId,
dataIds: selectedDataIds,
});
if (!response.success) {
throw new Error(`데이터 이동 실패: ${response.error || "알 수 없는 오류"}`);
}
toast.success(`${selectedRows.size}건의 데이터를 다음 단계로 이동했습니다`);