119 lines
5.2 KiB
JavaScript
119 lines
5.2 KiB
JavaScript
const mongoose = require('mongoose');
|
|
const connectDB = require('../config/db');
|
|
const User = require('../models/User');
|
|
const Scene = require('../models/Scene');
|
|
|
|
/**
|
|
* Script rà soát tính toàn vẹn của tourId và quyền sở hữu.
|
|
* Mục tiêu:
|
|
* 1. Phát hiện các Scene không có tourId (Mồ côi).
|
|
* 2. Phát hiện các Scene trỏ tourId vào một cảnh không tồn tại (Link hỏng).
|
|
* 3. Phát hiện rủi ro Scenario 2: Scene của người A nhưng tourId lại trỏ vào Tour của người B.
|
|
*/
|
|
const auditTourIds = async () => {
|
|
try {
|
|
console.log('--- BẮT ĐẦU RÀ SOÁT TOUR ID ---');
|
|
await connectDB();
|
|
|
|
// Lấy tất cả scene và populate thông tin người tạo
|
|
const scenes = await Scene.find().populate('createdBy', 'username');
|
|
console.log(`Đang kiểm tra ${scenes.length} bản ghi...\n`);
|
|
|
|
const report = {
|
|
orphan: [], // Không có tourId
|
|
brokenLink: [], // tourId trỏ vào hư vô
|
|
mismatchOwner: [], // Chủ sở hữu không khớp (Rủi ro Scenario 2)
|
|
validRoots: 0,
|
|
validChildren: 0
|
|
};
|
|
|
|
for (const scene of scenes) {
|
|
const sId = scene._id.toString();
|
|
|
|
// 1. Kiểm tra tồn tại tourId
|
|
// [ROBUST CHECK] Kiểm tra cả giá trị null, undefined và chuỗi rác
|
|
const tourIdRaw = scene.tourId;
|
|
if (!tourIdRaw || tourIdRaw === "" || tourIdRaw === "null" || tourIdRaw === "undefined") {
|
|
report.orphan.push({
|
|
id: sId,
|
|
name: scene.name || scene.title,
|
|
value: JSON.stringify(tourIdRaw) // In ra giá trị thực tế để debug
|
|
});
|
|
continue;
|
|
}
|
|
|
|
const tId = scene.tourId.toString();
|
|
|
|
// Trường hợp là Root (Cảnh gốc của chính nó)
|
|
if (sId === tId) {
|
|
report.validRoots++;
|
|
continue;
|
|
}
|
|
|
|
// Trường hợp là Child -> Kiểm tra quan hệ với cha
|
|
const rootScene = await Scene.findById(scene.tourId).populate('createdBy', 'username');
|
|
|
|
if (!rootScene) {
|
|
report.brokenLink.push({ id: sId, name: scene.name || scene.title, target: tId });
|
|
continue;
|
|
}
|
|
|
|
// 2. KIỂM TRA QUAN TRỌNG: Đồng nhất chủ sở hữu (Scenario 2)
|
|
// Nếu scene con có chủ sở hữu khác với scene gốc mà nó đang trỏ tourId vào,
|
|
// nghĩa là quyền riêng tư của nó đang bị điều khiển bởi một người khác.
|
|
const sceneOwner = scene.createdBy?._id?.toString() || scene.createdBy?.toString();
|
|
const rootOwner = rootScene.createdBy?._id?.toString() || rootScene.createdBy?.toString();
|
|
|
|
if (sceneOwner !== rootOwner) {
|
|
report.mismatchOwner.push({
|
|
childId: sId,
|
|
childName: scene.name || scene.title,
|
|
childOwner: scene.createdBy?.username || 'N/A',
|
|
parentId: tId,
|
|
parentName: rootScene.name || rootScene.title,
|
|
parentOwner: rootScene.createdBy?.username || 'N/A'
|
|
});
|
|
} else {
|
|
report.validChildren++;
|
|
}
|
|
}
|
|
|
|
// --- XUẤT BÁO CÁO ---
|
|
console.log('=== KẾT QUẢ RÀ SOÁT ===');
|
|
console.log(`- Scene gốc hợp lệ: ${report.validRoots}`);
|
|
console.log(`- Scene con hợp lệ: ${report.validChildren}`);
|
|
console.log('-----------------------');
|
|
|
|
if (report.orphan.length > 0) {
|
|
console.error(`[!] LỖI: ${report.orphan.length} Scene mồ côi (thiếu tourId):`);
|
|
report.orphan.forEach(x => console.log(` - ID: ${x.id} | Tên: ${x.name}`));
|
|
}
|
|
|
|
if (report.brokenLink.length > 0) {
|
|
console.error(`[!] LỖI: ${report.brokenLink.length} Scene trỏ vào Tour không tồn tại:`);
|
|
report.brokenLink.forEach(x => console.log(` - ID: ${x.id} | Tên: ${x.name} -> Target: ${x.target}`));
|
|
}
|
|
|
|
if (report.mismatchOwner.length > 0) {
|
|
console.warn(`[!] CẢNH BÁO: ${report.mismatchOwner.length} Scene bị "lây nhiễm" tourId (Nguy cơ Scenario 2):`);
|
|
report.mismatchOwner.forEach(x => {
|
|
console.log(` - Cảnh [${x.childName}] (ID: ${x.childId}) của user [${x.childOwner}]`);
|
|
console.log(` đang bị điều khiển bởi Tour [${x.parentName}] của user [${x.parentOwner}]`);
|
|
console.log(` => GIẢI PHÁP: Cần cập nhật tourId của cảnh này về chính nó.\n`);
|
|
});
|
|
}
|
|
|
|
if (report.orphan.length === 0 && report.brokenLink.length === 0 && report.mismatchOwner.length === 0) {
|
|
console.log('[✓] Database sạch sẽ. Không phát hiện lỗi tourId hay xâm lấn quyền sở hữu.');
|
|
}
|
|
|
|
console.log('\n--- HOÀN TẤT ---');
|
|
mongoose.connection.close();
|
|
process.exit(0);
|
|
} catch (err) {
|
|
console.error('Lỗi thực thi script:', err);
|
|
process.exit(1);
|
|
}
|
|
};
|
|
|
|
auditTourIds(); |