93 lines
4.1 KiB
JavaScript
93 lines
4.1 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const multer = require('multer');
|
|
const sharp = require('sharp');
|
|
|
|
const User = require('../models/User');
|
|
const Asset = require('../models/Asset');
|
|
const Scene = require('../models/Scene');
|
|
const Hotspot = require('../models/Hotspot');
|
|
const { protect } = require('../middlewares/authMiddleware');
|
|
const { ROLE_QUOTAS } = require('../middlewares/quotaMiddleware');
|
|
|
|
const uploadDir = process.env.UPLOAD_DIR ? path.resolve(process.env.UPLOAD_DIR) : path.join(__dirname, '../uploads');
|
|
const upload = multer({ dest: path.join(uploadDir, 'temp') });
|
|
|
|
// @route GET /api/users/search
|
|
router.get('/search', protect, async (req, res) => {
|
|
const query = req.query.q;
|
|
if (!query || query.length < 2) return res.json([]);
|
|
try {
|
|
const users = await User.find({
|
|
_id: { $ne: req.user._id },
|
|
$or: [{ username: { $regex: query, $options: 'i' } }, { email: { $regex: query, $options: 'i' } }]
|
|
}).select('username email').limit(10);
|
|
res.json(users);
|
|
} catch (error) { res.status(500).json({ message: error.message }); }
|
|
});
|
|
|
|
// @route GET /api/me/scenes
|
|
// @desc Lấy danh sách các cảnh do chính người dùng hiện tại tạo
|
|
router.get('/scenes', protect, async (req, res) => {
|
|
try {
|
|
const scenes = await Scene.find({ createdBy: req.user._id })
|
|
.populate('createdBy', 'username')
|
|
.populate('assetId')
|
|
.select('+views') // Đảm bảo lấy được trường views để hiển thị thống kê
|
|
.sort({ createdAt: -1 })
|
|
.lean();
|
|
|
|
// Kiểm tra xem mỗi scene có phải là scene con (được trỏ tới bởi hotspot khác) hay không
|
|
// Điều này giúp Frontend quyết định quyền thay đổi Privacy
|
|
for (let i = 0; i < scenes.length; i++) {
|
|
const isChild = await Hotspot.exists({ target_scene_id: scenes[i]._id });
|
|
scenes[i].isChildScene = !!isChild;
|
|
}
|
|
|
|
res.json(scenes);
|
|
} catch (error) {
|
|
res.status(500).json({ message: error.message });
|
|
}
|
|
});
|
|
|
|
// @route GET /api/me/profile
|
|
router.get('/profile', protect, async (req, res) => {
|
|
try {
|
|
const user = await User.findById(req.user._id).select('-password').lean();
|
|
const usage = await Asset.aggregate([{ $match: { uploadedBy: req.user._id } }, { $group: { _id: null, total: { $sum: "$fileSize" } } }]);
|
|
const currentUsage = usage.length > 0 ? usage[0].total : 0;
|
|
res.json({ ...user, storage: { used: currentUsage, quota: ROLE_QUOTAS[user.role] || ROLE_QUOTAS['Thành viên'] } });
|
|
} catch (error) { res.status(500).json({ message: error.message }); }
|
|
});
|
|
|
|
// @route PUT /api/me/profile
|
|
router.put('/profile', protect, upload.single('avatar'), async (req, res) => {
|
|
try {
|
|
const user = await User.findById(req.user._id);
|
|
const { fullName, email, username, password } = req.body;
|
|
|
|
if (fullName) user.fullName = fullName;
|
|
if (email) user.email = email;
|
|
if (username) user.username = username;
|
|
if (password && password.trim() !== '') user.password = password;
|
|
|
|
if (req.file) {
|
|
if (user.avatarUrl && user.avatarUrl.includes('avatar_')) {
|
|
const oldPath = path.join(uploadDir, user.avatarUrl.split('/').pop());
|
|
await fs.promises.unlink(oldPath).catch(() => {});
|
|
}
|
|
const avatarName = `avatar_${user._id}${path.extname(req.file.originalname)}`;
|
|
const avatarPath = path.join(uploadDir, avatarName);
|
|
await sharp(req.file.path).resize(200, 200).toFile(avatarPath);
|
|
user.avatarUrl = `/api/assets/view_avatar/${avatarName}`;
|
|
await fs.promises.unlink(req.file.path).catch(() => {});
|
|
}
|
|
|
|
await user.save({ validateBeforeSave: false });
|
|
res.json({ message: 'Hồ sơ đã được cập nhật', user: { id: user._id, username: user.username, role: user.role } });
|
|
} catch (error) { res.status(400).json({ message: error.message }); }
|
|
});
|
|
|
|
module.exports = router; |