Sửa lỗi tạo docker
This commit is contained in:
@@ -4,6 +4,20 @@ const User = require('../models/User');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
/**
|
||||
* @route GET /api/auth/init-status
|
||||
* @desc Check if the system has at least one admin
|
||||
* @access Public
|
||||
*/
|
||||
router.get('/init-status', async (req, res) => {
|
||||
try {
|
||||
const userCount = await User.countDocuments();
|
||||
res.json({ initialized: userCount > 0 });
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @route POST /api/auth/register
|
||||
* @desc Register a new user
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const { Queue } = require('bullmq');
|
||||
const IORedis = require('ioredis');
|
||||
|
||||
// Cấu hình kết nối Redis (Mặc định localhost:6379)
|
||||
// Cấu hình kết nối Redis sử dụng biến môi trường từ Docker
|
||||
const connection = new IORedis({
|
||||
host: process.env.REDIS_HOST || '127.0.0.1',
|
||||
port: process.env.REDIS_PORT || 6379,
|
||||
maxRetriesPerRequest: null
|
||||
});
|
||||
|
||||
|
||||
@@ -17,10 +17,17 @@ const { imageQueue } = require('./imageQueue');
|
||||
const { deleteSceneCascade, propagateScenePrivacy } = require('../utils/sceneHelper');
|
||||
|
||||
const uploadDir = process.env.UPLOAD_DIR ? path.resolve(process.env.UPLOAD_DIR) : path.join(__dirname, '../uploads');
|
||||
const tempDir = path.join(uploadDir, 'temp');
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => cb(null, tempDir),
|
||||
destination: (req, file, cb) => {
|
||||
// req.user đã được populate bởi protect middleware
|
||||
const userId = req.user._id.toString();
|
||||
const userTempDir = path.join(uploadDir, userId, 'temp');
|
||||
if (!fs.existsSync(userTempDir)) {
|
||||
fs.mkdirSync(userTempDir, { recursive: true });
|
||||
}
|
||||
cb(null, userTempDir);
|
||||
},
|
||||
filename: (req, file, cb) => cb(null, `${Date.now()}_${crypto.randomBytes(4).toString('hex')}${path.extname(file.originalname)}`)
|
||||
});
|
||||
const upload = multer({ storage });
|
||||
@@ -54,8 +61,16 @@ router.post('/', protect, uploadSinglePanorama, checkQuota, async (req, res) =>
|
||||
const latitude = Number(lat) || 0;
|
||||
const longitude = Number(lng) || 0;
|
||||
const tempFilePath = req.file.path;
|
||||
|
||||
// Tạo thư mục lưu trữ chính cho User nếu chưa có
|
||||
const userId = req.user._id.toString();
|
||||
const userUploadDir = path.join(uploadDir, userId);
|
||||
if (!fs.existsSync(userUploadDir)) {
|
||||
fs.mkdirSync(userUploadDir, { recursive: true });
|
||||
}
|
||||
|
||||
const processedFileName = `processed_${req.file.filename}.jpg`;
|
||||
const processedFilePath = path.join(uploadDir, processedFileName);
|
||||
const processedFilePath = path.join(userUploadDir, processedFileName);
|
||||
|
||||
const asset = new Asset({
|
||||
filePath: tempFilePath,
|
||||
@@ -143,7 +158,6 @@ router.get('/', optionalAuth, async (req, res) => {
|
||||
};
|
||||
}
|
||||
|
||||
console.log(`[SceneRoutes] GET /api/scenes - Final Query for user ${req.user?._id || 'Guest'}:`, JSON.stringify(finalQuery));
|
||||
const scenes = await Scene.find(finalQuery)
|
||||
.populate('createdBy', 'username')
|
||||
.populate('tourId') // Nạp thông tin Tour để Frontend nhận diện
|
||||
@@ -154,6 +168,70 @@ router.get('/', optionalAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// @route GET /api/share/:id
|
||||
// @desc Trang trung gian hỗ trợ Open Graph (Facebook, Zalo,...)
|
||||
router.get('/share/:id', async (req, res) => {
|
||||
try {
|
||||
const scene = await Scene.findById(req.params.id).populate('tourId');
|
||||
if (!scene) return res.status(404).send('Không tìm thấy cảnh 3D');
|
||||
|
||||
const tour = scene.tourId;
|
||||
const title = tour ? tour.name : (scene.name || 'Virtual Tour 3D');
|
||||
const description = tour ? tour.description : (scene.description || 'Khám phá không gian 360 độ chân thực');
|
||||
|
||||
// Xác định token (ưu tiên query token, sau đó là token của tour/scene nếu có)
|
||||
const token = req.query.token || scene.shareToken || (tour && tour.shareToken) || '';
|
||||
|
||||
// Xử lý Protocol/Host để tạo URL tuyệt đối
|
||||
const protocol = req.headers['x-forwarded-proto'] || req.protocol;
|
||||
const host = req.get('host');
|
||||
const baseUrl = `${protocol}://${host}`;
|
||||
|
||||
// URL ảnh thumbnail gọi sang Asset API với cờ watermark
|
||||
const imageUrl = `${baseUrl}/api/assets/view/${scene.assetId}?watermark=true${token ? '&token=' + token : ''}`;
|
||||
|
||||
// URL thực tế của ứng dụng để redirect người dùng
|
||||
const appUrl = `${baseUrl}/?sceneId=${scene._id}${token ? '&token=' + token : ''}`;
|
||||
|
||||
res.send(`
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>${title}</title>
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="${appUrl}">
|
||||
<meta property="og:title" content="${title}">
|
||||
<meta property="og:description" content="${description}">
|
||||
<meta property="og:image" content="${imageUrl}">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:title" content="${title}">
|
||||
<meta property="twitter:description" content="${description}">
|
||||
<meta property="twitter:image" content="${imageUrl}">
|
||||
|
||||
<!-- Chuyển hướng người dùng về trang chủ để mở viewer -->
|
||||
<script type="text/javascript">
|
||||
window.location.href = "${appUrl}";
|
||||
</script>
|
||||
</head>
|
||||
<body style="font-family: sans-serif; text-align: center; padding-top: 50px; background: #1a1a1a; color: #fff;">
|
||||
<h2>${title}</h2>
|
||||
<p>Đang tải không gian 3D, vui lòng đợi...</p>
|
||||
</body>
|
||||
</html>`);
|
||||
} catch (error) {
|
||||
console.error("[Share Error]", error);
|
||||
res.status(500).send('Lỗi máy chủ');
|
||||
}
|
||||
});
|
||||
|
||||
// @route GET /api/scenes/:id
|
||||
router.get('/:id', optionalAuth, async (req, res) => {
|
||||
try {
|
||||
@@ -294,8 +372,14 @@ router.put('/:id', protect, uploadSinglePanorama, async (req, res) => {
|
||||
}
|
||||
|
||||
if (req.file) {
|
||||
const userId = req.user._id.toString();
|
||||
const userUploadDir = path.join(uploadDir, userId);
|
||||
if (!fs.existsSync(userUploadDir)) {
|
||||
fs.mkdirSync(userUploadDir, { recursive: true });
|
||||
}
|
||||
|
||||
const processedFileName = `processed_${req.file.filename}.jpg`;
|
||||
const processedFilePath = path.join(uploadDir, processedFileName);
|
||||
const processedFilePath = path.join(userUploadDir, processedFileName);
|
||||
await resizeTo8K(req.file.path, processedFilePath);
|
||||
await injectGPSCoordinates(processedFilePath, scene.gps.lat, scene.gps.lng);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user