Lỗi có thể di chuyển tù sharedlink sang public nhưng không có hotspot quay lại

This commit is contained in:
2026-06-11 16:27:37 +07:00
parent be149f26ca
commit 0434837026
7 changed files with 1055 additions and 47 deletions
+28 -6
View File
@@ -117,7 +117,16 @@ router.get('/', optionalAuth, async (req, res) => {
// Quyền cơ bản: Công khai hoặc là chủ sở hữu/thành viên được chia sẻ
let baseQuery = req.user && req.user.role !== 'guest'
? { $or: [{ privacy: 'public' }, { tourId: { $in: publicTourIds } }, { createdBy: req.user._id }, { sharedWith: req.user._id }, { sharedEmails: req.user.email }] }
? {
$or: [
{ privacy: 'public' },
{ privacy: 'member' },
{ tourId: { $in: publicTourIds } },
{ createdBy: req.user._id },
{ sharedWith: req.user._id },
{ sharedEmails: req.user.email }
]
}
: { $or: [{ privacy: 'public' }, { tourId: { $in: publicTourIds } }] };
let finalQuery = baseQuery;
@@ -148,6 +157,8 @@ router.get('/', optionalAuth, async (req, res) => {
// @route GET /api/scenes/:id
router.get('/:id', optionalAuth, async (req, res) => {
try {
console.log(`[Backend-Scene] Yêu cầu chi tiết: ${req.params.id}. User: ${req.user?._id || 'Guest'}, QueryToken: ${req.query.token || 'N/A'}`);
const scene = await Scene.findById(req.params.id)
.populate('createdBy', 'username')
.populate('assetId')
@@ -165,18 +176,23 @@ router.get('/:id', optionalAuth, async (req, res) => {
const isTourTokenValid = tour.shareToken && (!tour.shareTokenExpires || new Date() < tour.shareTokenExpires);
const userEmail = req.user ? req.user.email : null;
let hasAccess = tour.privacy === 'public' || isOwner || isAdmin ||
// [FIX] Cho phép truy cập nếu bản thân Scene CÔNG KHAI hoặc Tour CÔNG KHAI
let hasAccess = tour.privacy === 'public' || scene.privacy === 'public' || isOwner || isAdmin ||
(scene.privacy === 'shared' && req.query.token === scene.shareToken && isSceneTokenValid) || // Access via scene's token
(tour.privacy === 'shared' && req.query.token === tour.shareToken && isTourTokenValid) || // Access via tour's token
(tour.privacy === 'member' && req.user && req.user._id && ( // Access for members
(tour.privacy === 'member' && req.user && req.user._id && req.user.role !== 'guest') || // Access for any logged-in member
(tour.privacy === 'member' && req.user && req.user._id && ( // Specific shared members (legacy support)
tour.sharedWith.some(u => u.toString() === req.user._id.toString()) ||
(userEmail && tour.sharedEmails.includes(userEmail))
));
if (req.query.token) {
console.log(`[Backend-Auth] Token: ${req.query.token}. Match Scene: ${req.query.token === scene.shareToken}, Match Tour: ${req.query.token === tour.shareToken}, Access: ${hasAccess}`);
}
// [BRIDGE ACCESS LOGIC]
// Nếu chưa có quyền, kiểm tra xem người dùng có đến từ một cảnh hợp lệ thuộc Tour khác không
if (!hasAccess && req.query.token) {
// Tìm tất cả các cảnh (parent) có hotspot trỏ đến cảnh hiện tại
const potentialParents = await Hotspot.find({ target_scene_id: scene._id }).distinct('parent_scene_id');
if (potentialParents.length > 0) {
// Kiểm tra xem có cảnh cha nào sở hữu shareToken này và còn hạn không
@@ -185,11 +201,17 @@ router.get('/:id', optionalAuth, async (req, res) => {
shareToken: req.query.token,
$or: [{ shareTokenExpires: null }, { shareTokenExpires: { $gt: new Date() } }]
});
if (authorizedParentExists) hasAccess = true;
if (authorizedParentExists) {
hasAccess = true;
console.log(`[Backend-Bridge] Quyền được chấp thuận qua Scene cha.`);
}
}
}
if (!hasAccess) return res.status(403).json({ message: 'Bạn không được phép di chuyển đến cảnh này' });
if (!hasAccess) {
console.warn(`[Backend-Denied] Scene: ${scene._id}, TourPrivacy: ${tour.privacy}, ScenePrivacy: ${scene.privacy}`);
return res.status(403).json({ message: 'Bạn không có quyền truy cập cảnh này.' });
}
// Increment view count if not owner/admin and not a bot
if (!isOwner && !isAdmin && !req.headers['user-agent']?.match(/bot|crawl|spider/i)) {