diff --git a/internal/server/static/policy-editor.js b/internal/server/static/policy-editor.js index 14373d8..e953e38 100644 --- a/internal/server/static/policy-editor.js +++ b/internal/server/static/policy-editor.js @@ -12,8 +12,6 @@ let appState = { availableRoles: [], templates: [], isDirty: false, - originalRules: null, // Store original rules to detect changes - originalRBAC: null, // Store original RBAC to detect changes filters: { ruleSearch: '', category: '' @@ -1234,42 +1232,6 @@ async function handleApplyTemplate(e) { } // ==================== Save & Load ==================== -// Helper function to create stable JSON string for comparison -// Recursively sorts object keys to ensure consistent comparison -function createStableJSON(obj) { - if (obj === null || obj === undefined) { - return JSON.stringify(obj); - } - - if (typeof obj !== 'object') { - return JSON.stringify(obj); - } - - if (Array.isArray(obj)) { - // Recursively process array elements - const processedArray = obj.map(item => { - if (item && typeof item === 'object') { - return JSON.parse(createStableJSON(item)); - } - return item; - }); - return JSON.stringify(processedArray); - } - - // Recursively process object properties - const sorted = {}; - Object.keys(obj).sort().forEach(key => { - const value = obj[key]; - if (value && typeof value === 'object') { - sorted[key] = JSON.parse(createStableJSON(value)); - } else { - sorted[key] = value; - } - }); - - return JSON.stringify(sorted); -} - async function savePolicy() { if (appState.settings.confirmSave) { if (!confirm('정책을 저장하시겠습니까?')) return; @@ -1326,70 +1288,27 @@ async function savePolicy() { document.getElementById('floating-save-btn').classList.remove('ring-4', 'ring-yellow-400', 'animate-pulse'); showToast('정책이 성공적으로 저장되었습니다!'); - console.log('[DEBUG] Policy saved successfully, checking for changes...'); - - // Check if rules or RBAC were changed and ask about conversion - const currentRules = createStableJSON(appState.policy.rules || []); - const currentRBAC = createStableJSON(appState.policy.rbac || {}); - const rulesChanged = appState.originalRules && (appState.originalRules !== currentRules); - const rbacChanged = appState.originalRBAC && (appState.originalRBAC !== currentRBAC); - - // Check if code-policy.json exists in the policy directory - const policyPath = appState.settings.policyPath || '.sym/user-policy.json'; - const policyDir = policyPath.substring(0, policyPath.lastIndexOf('/')); - const codePolicyPath = policyDir + '/code-policy.json'; - let codePolicyExists = false; - - try { - const response = await fetch(codePolicyPath); - codePolicyExists = response.ok; - } catch (error) { - codePolicyExists = false; - } - - console.log('=== Policy Change Detection ==='); - console.log('Original rules:', appState.originalRules ? appState.originalRules.substring(0, 100) + '...' : 'NULL'); - console.log('Current rules:', currentRules.substring(0, 100) + '...'); - console.log('Original RBAC:', appState.originalRBAC ? appState.originalRBAC.substring(0, 100) + '...' : 'NULL'); - console.log('Current RBAC:', currentRBAC.substring(0, 100) + '...'); - console.log('Rules changed?', rulesChanged); - console.log('RBAC changed?', rbacChanged); - console.log('code-policy.json exists?', codePolicyExists); - console.log('============================'); - - if (rulesChanged || rbacChanged || !codePolicyExists) { - const changedItems = []; - if (rulesChanged) changedItems.push('규칙'); - if (rbacChanged) changedItems.push('RBAC 설정'); - if (!codePolicyExists) changedItems.push('code-policy.json 파일이 없음'); - - const message = changedItems.length > 0 ? - `${changedItems.join(', ')}.\n\n` + - 'linter 설정 파일(ESLint, Checkstyle, PMD 등)을 자동으로 생성하시겠습니까?\n\n' + - '이 작업은 설정된 LLM Provider를 사용하며 몇 분 정도 소요될 수 있습니다.' : - 'linter 설정 파일(ESLint, Checkstyle, PMD 등)을 자동으로 생성하시겠습니까?\n\n' + - '이 작업은 설정된 LLM Provider를 사용하며 몇 분 정도 소요될 수 있습니다.'; - - const shouldConvert = confirm(message); - - if (shouldConvert) { - try { - showToast('정책 변환 중... 잠시만 기다려주세요', 'info'); - const convertResult = await API.convertPolicy(); - showToast( - `변환 완료! ${convertResult.filesWritten.length}개의 파일이 생성되었습니다.`, - 'success' - ); - console.log('Convert result:', convertResult); - } catch (error) { - console.error('Conversion failed:', error); - showToast('변환 실패: ' + error.message, 'error'); - } + // Always ask user about conversion after save + const message = + '저장이 완료되었습니다.\n\n' + + 'linter 설정 파일을 생성/갱신하시겠습니까?\n' + + '(code-policy.json, ESLint, Checkstyle, PMD 등)\n\n' + + '• 확인: LLM을 사용하여 설정 파일 생성\n' + + '• 취소: 현재 설정 유지'; + + if (confirm(message)) { + try { + showToast('정책 변환 중... 잠시만 기다려주세요', 'info'); + const convertResult = await API.convertPolicy(); + showToast( + `변환 완료! ${convertResult.filesWritten.length}개의 파일이 생성되었습니다.`, + 'success' + ); + console.log('Convert result:', convertResult); + } catch (error) { + console.error('Conversion failed:', error); + showToast('변환 실패: ' + error.message, 'error'); } - - // Update original rules and RBAC to current state to avoid re-asking - appState.originalRules = currentRules; - appState.originalRBAC = currentRBAC; } } catch (error) { console.error('Failed to save policy:', error); @@ -1400,12 +1319,7 @@ async function savePolicy() { async function loadPolicy() { try { appState.policy = await API.getPolicy(); - // Store original rules and RBAC for change detection (using stable JSON) - appState.originalRules = createStableJSON(appState.policy.rules || []); - appState.originalRBAC = createStableJSON(appState.policy.rbac || {}); console.log('Policy loaded. Rules count:', appState.policy.rules.length); - console.log('Original rules stored:', appState.originalRules.substring(0, 100) + '...'); - console.log('Original RBAC stored:', appState.originalRBAC.substring(0, 100) + '...'); renderAll(); showToast('정책을 불러왔습니다'); } catch (error) {