MERN社交应用实现帖子公开/私密可见性功能技术问询
帖子可见性功能实现方案
1. 修正Post模型缩进问题(已初步实现)
你的Post模型中visibility字段缩进有误,修正后确保schema语法正确:
const mongoose = require("mongoose"); const postSchema = new mongoose.Schema({ caption: String, image: { public_id: String, url: String, }, owner: { type: mongoose.Schema.Types.ObjectId, ref: "User", }, createdAt: { type: Date, default: Date.now, }, likes: [ { type: mongoose.Schema.Types.ObjectId, ref: "User", }, ], comments: [ { user: { type: mongoose.Schema.Types.ObjectId, ref: "User", }, comment: { type: String, required: true, }, }, ], // 修正缩进,确保字段属于schema结构 visibility: { type: String, enum: ["public", "private"], default: "public" }, }); module.exports = mongoose.model("Post", postSchema);
2. 更新创建帖子接口
在创建帖子时接收前端传入的可见性参数,默认使用public:
exports.createPost = async (req, res) => { try { const myCloud = await cloudinary.v2.uploader.upload(req.body.image, { folder: "posts", }); const newPostData = { caption: req.body.caption, image: { public_id: myCloud.public_id, url: myCloud.secure_url, }, owner: req.user._id, // 新增:接收前端传入的可见性参数,无则用默认值 visibility: req.body.visibility || "public" }; const post = await Post.create(newPostData); const user = await User.findById(req.user._id); user.posts.unshift(post._id); await user.save(); res.status(201).json({ success: true, message: "Post created", post }); } catch (error) { res.status(500).json({ success: false, message: error.message, }); } };
3. 实现帖子列表的权限过滤逻辑
根据不同场景返回符合权限的帖子:
场景一:获取当前用户的所有帖子
直接返回自己的全部帖子,不受可见性限制:
exports.getMyPosts = async (req, res) => { try { const posts = await Post.find({ owner: req.user._id }) .populate("owner", "name avatar") .populate("likes", "name avatar") .populate("comments.user", "name avatar"); res.status(200).json({ success: true, posts }); } catch (error) { res.status(500).json({ success: false, message: error.message }); } };
场景二:获取他人的帖子列表
- 若当前用户是对方的关注者或本人,返回所有帖子
- 否则仅返回公开帖子:
exports.getUserPosts = async (req, res) => { try { const targetUser = await User.findById(req.params.id); if (!targetUser) { return res.status(404).json({ success: false, message: "User not found" }); } const isSelf = req.user._id.toString() === req.params.id; const isFollower = targetUser.followers.includes(req.user._id); let query = { owner: req.params.id }; if (!isSelf && !isFollower) { query.visibility = "public"; } const posts = await Post.find(query) .populate("owner", "name avatar") .populate("likes", "name avatar") .populate("comments.user", "name avatar"); res.status(200).json({ success: true, posts }); } catch (error) { res.status(500).json({ success: false, message: error.message }); } };
场景三:首页信息流(关注用户的帖子)
返回自己的所有帖子 + 关注用户的公开帖子(或关注用户的全部帖子,根据需求调整):
exports.getFeed = async (req, res) => { try { const currentUser = await User.findById(req.user._id); const followingIds = [...currentUser.following, req.user._id]; const posts = await Post.find({ owner: { $in: followingIds }, $or: [ { visibility: "public" }, { owner: req.user._id } ] }) .populate("owner", "name avatar") .populate("likes", "name avatar") .populate("comments.user", "name avatar") .sort({ createdAt: -1 }); res.status(200).json({ success: true, posts }); } catch (error) { res.status(500).json({ success: false, message: error.message }); } };
4. 点赞/评论的权限控制
确保只有有权限的用户才能操作私密帖子:
exports.likePost = async (req, res) => { try { const post = await Post.findById(req.params.id); if (!post) { return res.status(404).json({ success: false, message: "Post not found" }); } // 检查操作权限:公开帖所有人可操作,私密帖仅作者或关注者可操作 const hasPermission = post.visibility === "public" || post.owner.toString() === req.user._id.toString() || (await User.findById(post.owner)).followers.includes(req.user._id); if (!hasPermission) { return res.status(403).json({ success: false, message: "You can't interact with this private post" }); } // 原有点赞逻辑 if (post.likes.includes(req.user._id)) { post.likes = post.likes.filter(id => id.toString() !== req.user._id.toString()); } else { post.likes.push(req.user._id); } await post.save(); res.status(200).json({ success: true, message: post.likes.includes(req.user._id) ? "Post liked" : "Post unliked" }); } catch (error) { res.status(500).json({ success: false, message: error.message }); } };
5. 前端配合修改
- 创建帖子页面添加下拉选择框,提供「公开」「私密」选项,提交时将
visibility参数传给后端 - 展示帖子时,根据
visibility字段添加标识(如锁形图标)区分私密帖子 - 访问他人主页时,若没有权限查看私密帖子,隐藏相关内容
内容的提问来源于stack exchange,提问作者Akash Das
相关产品推荐
相关产品推荐

