Files

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;