mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
reimplement PostController
This commit is contained in:
parent
7cf549d65f
commit
5ad8dbed87
@ -1,178 +1,24 @@
|
||||
import { Controller } from "linebridge/dist/server"
|
||||
import { Schematized } from "../../lib"
|
||||
import { Post, User } from "../../models"
|
||||
|
||||
import { CreatePost, ToogleLike, GetPostsFeed, GetPostData } from "./methods"
|
||||
|
||||
export default class PostsController extends Controller {
|
||||
static refName = "PostsController"
|
||||
//static useMiddlewares = ["withAuthentication"]
|
||||
|
||||
methods = {
|
||||
createPost: async (payload) => {
|
||||
const { user_id, message, additions } = payload
|
||||
|
||||
const userData = await User.findById(user_id)
|
||||
|
||||
const post = new Post({
|
||||
user_id: typeof user_id === "object" ? user_id.toString() : user_id,
|
||||
message: String(message).toString(),
|
||||
additions: additions ?? [],
|
||||
created_at: new Date().getTime(),
|
||||
})
|
||||
|
||||
await post.save()
|
||||
|
||||
global.wsInterface.io.emit(`post.new`, {
|
||||
...post.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.new.${post.user_id}`, {
|
||||
...post.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
|
||||
return post
|
||||
},
|
||||
toogleLike: async (payload) => {
|
||||
const { post_id, user_id } = payload
|
||||
|
||||
const post = await Post.findById(post_id)
|
||||
|
||||
if (post.likes.includes(user_id)) {
|
||||
return this.methods.unlikePost({ post_id, user_id })
|
||||
} else {
|
||||
return this.methods.likePost({ post_id, user_id })
|
||||
}
|
||||
},
|
||||
likePost: async (payload) => {
|
||||
const { user_id, post_id } = payload
|
||||
|
||||
const userData = await User.findById(user_id)
|
||||
const postData = await Post.findById(post_id)
|
||||
|
||||
if (postData.likes.includes(user_id)) {
|
||||
postData.likes = postData.likes.filter(id => id !== user_id)
|
||||
await postData.save()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
postData.likes.push(user_id)
|
||||
|
||||
await this.savePostData(postData)
|
||||
|
||||
global.wsInterface.io.emit(`post.like`, {
|
||||
...postData.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.like.${postData.user_id}`, {
|
||||
...postData.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.like.${post_id}`, postData.toObject().likes)
|
||||
|
||||
return postData
|
||||
},
|
||||
unlikePost: async (payload) => {
|
||||
const { user_id, post_id } = payload
|
||||
|
||||
const userData = await User.findById(user_id)
|
||||
const postData = await Post.findById(post_id)
|
||||
|
||||
postData.likes = postData.likes.filter(id => id !== user_id)
|
||||
|
||||
await this.savePostData(postData)
|
||||
|
||||
global.wsInterface.io.emit(`post.unlike`, {
|
||||
...postData.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.unlike.${postData.user_id}`, {
|
||||
...postData.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.unlike.${post_id}`, postData.toObject().likes)
|
||||
|
||||
return postData
|
||||
},
|
||||
deletePost: async (payload) => {
|
||||
const { post_id, user_id } = payload
|
||||
|
||||
if (!user_id) {
|
||||
throw new Error("user_id not provided")
|
||||
}
|
||||
|
||||
const postData = await Post.findById(post_id)
|
||||
|
||||
if (!postData) {
|
||||
throw new Error("Post not found")
|
||||
}
|
||||
|
||||
const hasAdmin = await this.methods.hasAdmin({ user_id })
|
||||
|
||||
// check if user is the owner of the post
|
||||
if (postData.user_id !== user_id && !hasAdmin) {
|
||||
throw new Error("You are not allowed to delete this post")
|
||||
}
|
||||
|
||||
await postData.remove()
|
||||
global.wsInterface.io.emit(`post.delete`, post_id)
|
||||
},
|
||||
hasAdmin: async (payload) => {
|
||||
const { user_id } = payload
|
||||
|
||||
if (!user_id) {
|
||||
return false
|
||||
}
|
||||
|
||||
const userData = await User.findById(user_id)
|
||||
|
||||
if (!userData) {
|
||||
return false
|
||||
}
|
||||
|
||||
return userData.roles.includes("admin")
|
||||
}
|
||||
}
|
||||
|
||||
savePostData = async (post) => {
|
||||
await post.save()
|
||||
|
||||
global.wsInterface.io.emit(`post.dataUpdate`, post.toObject())
|
||||
global.wsInterface.io.emit(`post.dataUpdate.${post._id}`, post.toObject())
|
||||
}
|
||||
|
||||
get = {
|
||||
"/feed": {
|
||||
fn: Schematized({
|
||||
select: ["user_id"]
|
||||
}, async (req, res) => {
|
||||
const feedLimit = req.query?.limit ?? 20
|
||||
const feedTrimIndex = req.query?.trim ?? 0
|
||||
|
||||
// make sure that sort by date descending
|
||||
// trim index is used to get the last n posts
|
||||
let posts = await Post.find(req.selection)
|
||||
.sort({ created_at: -1 })
|
||||
.skip(feedTrimIndex)
|
||||
.limit(feedLimit)
|
||||
|
||||
// fetch and add user data to each post
|
||||
posts = posts.map(async (post, index) => {
|
||||
const user = await User.findById(post.user_id)
|
||||
|
||||
if (feedTrimIndex > 0) {
|
||||
index = Number(feedTrimIndex) + Number(index)
|
||||
}
|
||||
|
||||
return {
|
||||
...post.toObject(),
|
||||
user: user.toObject(),
|
||||
key: index,
|
||||
}
|
||||
let posts = await GetPostsFeed({
|
||||
feedLimit: req.query?.limit,
|
||||
feedTrimIndex: req.query?.trim,
|
||||
from_user_id: req.query?.user_id,
|
||||
for_user_id: req.user?._id,
|
||||
})
|
||||
|
||||
posts = await Promise.all(posts)
|
||||
|
||||
return res.json(posts)
|
||||
})
|
||||
},
|
||||
@ -181,38 +27,33 @@ export default class PostsController extends Controller {
|
||||
select: ["post_id"],
|
||||
required: ["post_id"]
|
||||
}, async (req, res) => {
|
||||
if (typeof req.selection.post_id !== "string") {
|
||||
return res.status(400).json({
|
||||
error: "post_id must be a string"
|
||||
})
|
||||
}
|
||||
let post = await GetPostData({
|
||||
post_id: req.query?.post_id,
|
||||
}).catch((error) => {
|
||||
res.status(404).json({ error: error.message })
|
||||
|
||||
const post = await Post.findById(req.selection.post_id).catch(() => null)
|
||||
|
||||
if (!post) {
|
||||
return res.status(404).json({
|
||||
error: "Post not found"
|
||||
})
|
||||
}
|
||||
|
||||
const user = await User.findById(post.user_id)
|
||||
|
||||
return res.json({
|
||||
...post.toObject(),
|
||||
user: user.toObject(),
|
||||
return null
|
||||
})
|
||||
|
||||
if (!post) return
|
||||
|
||||
return res.json(post)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
put = {
|
||||
|
||||
}
|
||||
|
||||
post = {
|
||||
"/post": {
|
||||
middlewares: ["withAuthentication"],
|
||||
fn: Schematized({
|
||||
required: ["message"],
|
||||
select: ["message", "additions"],
|
||||
}, async (req, res) => {
|
||||
const post = await this.methods.createPost({
|
||||
const post = await CreatePost({
|
||||
user_id: req.user.id,
|
||||
message: req.selection.message,
|
||||
additions: req.selection.additions,
|
||||
@ -225,21 +66,20 @@ export default class PostsController extends Controller {
|
||||
middlewares: ["withAuthentication"],
|
||||
fn: Schematized({
|
||||
required: ["post_id"],
|
||||
select: ["post_id"],
|
||||
select: ["post_id", "to"],
|
||||
}, async (req, res) => {
|
||||
const post = await this.methods.toogleLike({
|
||||
const post = await ToogleLike({
|
||||
user_id: req.user._id.toString(),
|
||||
post_id: req.selection.post_id,
|
||||
to: req.selection.to,
|
||||
}).catch((err) => {
|
||||
res.status(400).json({
|
||||
error: err.message
|
||||
})
|
||||
return false
|
||||
})
|
||||
|
||||
if (!post) {
|
||||
return res.json({
|
||||
error: err.message,
|
||||
success: false
|
||||
})
|
||||
}
|
||||
if (!post) return
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@ -247,100 +87,30 @@ export default class PostsController extends Controller {
|
||||
})
|
||||
})
|
||||
},
|
||||
"/like": {
|
||||
"/post/:post_id/toogle_like": {
|
||||
middlewares: ["withAuthentication"],
|
||||
fn: Schematized({
|
||||
required: ["post_id"],
|
||||
select: ["post_id"],
|
||||
select: ["to"],
|
||||
}, async (req, res) => {
|
||||
const post = await this.methods.likePost({
|
||||
const post = await ToogleLike({
|
||||
user_id: req.user._id.toString(),
|
||||
post_id: req.selection.post_id,
|
||||
post_id: req.params.post_id,
|
||||
to: req.selection.to,
|
||||
}).catch((err) => {
|
||||
res.status(400).json({
|
||||
error: err.message
|
||||
})
|
||||
return false
|
||||
})
|
||||
|
||||
if (!post) {
|
||||
return res.json({
|
||||
success: false,
|
||||
})
|
||||
}
|
||||
if (!post) return
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
post
|
||||
})
|
||||
})
|
||||
},
|
||||
"/unlike": {
|
||||
middlewares: ["withAuthentication"],
|
||||
fn: Schematized({
|
||||
required: ["post_id"],
|
||||
select: ["post_id"],
|
||||
}, async (req, res) => {
|
||||
const post = await this.methods.unlikePost({
|
||||
user_id: req.user._id.toString(),
|
||||
post_id: req.selection.post_id,
|
||||
}).catch((err) => {
|
||||
return false
|
||||
})
|
||||
|
||||
if (!post) {
|
||||
return res.json({
|
||||
success: false,
|
||||
})
|
||||
}
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
post = {
|
||||
"/fix_posts_data": {
|
||||
public: false, // This will be functional with next versions of linebridge (Will exclude this endpoint from the server endpoint map)
|
||||
middlewares: ["withAuthentication", "onlyAdmin"],
|
||||
fn: async (req, res) => {
|
||||
const posts = await Post.find()
|
||||
|
||||
for await (let post of posts) {
|
||||
if (Array.isArray(post.additions) && post.additions.length > 0) {
|
||||
post.additions = post.additions.map((addition) => {
|
||||
// fix strings additions
|
||||
if (typeof addition === "string") {
|
||||
addition = {
|
||||
url: addition,
|
||||
}
|
||||
}
|
||||
|
||||
// replace insecure http urls with https
|
||||
if (addition.url.startsWith("http://")) {
|
||||
addition.url = addition.url.replace("http://", "https://")
|
||||
}
|
||||
|
||||
// fix old local path resolve (${host}/upload/id => ${host}/storage/id)
|
||||
const hostnamePath = addition.url.replace(/^https?:\/\//, "")
|
||||
if (hostnamePath.startsWith(`${global.publicHostname}/upload`)) {
|
||||
addition.url = addition.url.replace(`${global.publicHostname}/upload`, `${global.publicHostname}/storage`)
|
||||
}
|
||||
|
||||
console.log(`Processed addition >`, addition)
|
||||
|
||||
return addition
|
||||
})
|
||||
}
|
||||
|
||||
await Post.findByIdAndUpdate(post._id, {
|
||||
additions: post.additions,
|
||||
})
|
||||
}
|
||||
|
||||
return res.json({
|
||||
success: true
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
delete = {
|
||||
@ -350,20 +120,23 @@ export default class PostsController extends Controller {
|
||||
required: ["post_id"],
|
||||
select: ["post_id"],
|
||||
}, async (req, res) => {
|
||||
await this.methods.deletePost({
|
||||
const post = await DeletePost({
|
||||
post_id: req.selection.post_id,
|
||||
user_id: req.user._id.toString(),
|
||||
by_user_id: req.user._id.toString(),
|
||||
}).catch((err) => {
|
||||
res.status(400).json({
|
||||
error: err.message
|
||||
})
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if (!post) return
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
post
|
||||
})
|
||||
.then(() => {
|
||||
return res.json({
|
||||
success: true,
|
||||
})
|
||||
})
|
||||
.catch((err) => {
|
||||
return res.status(500).json({
|
||||
message: err.message,
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
import { Post, User } from "../../../models"
|
||||
|
||||
export default async (payload) => {
|
||||
const { user_id, message, additions } = payload
|
||||
|
||||
const userData = await User.findById(user_id)
|
||||
|
||||
const post = new Post({
|
||||
user_id: typeof user_id === "object" ? user_id.toString() : user_id,
|
||||
message: String(message).toString(),
|
||||
additions: additions ?? [],
|
||||
created_at: new Date().getTime(),
|
||||
})
|
||||
|
||||
await post.save()
|
||||
|
||||
global.wsInterface.io.emit(`post.new`, {
|
||||
...post.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.new.${post.user_id}`, {
|
||||
...post.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
|
||||
return post
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import { Post, User } from "../../../models"
|
||||
|
||||
async function hasAdmin(user_id) {
|
||||
if (!user_id) {
|
||||
return false
|
||||
}
|
||||
|
||||
const userData = await User.findById(user_id)
|
||||
|
||||
if (!userData) {
|
||||
return false
|
||||
}
|
||||
|
||||
return userData.roles.includes("admin")
|
||||
}
|
||||
|
||||
export default async (payload) => {
|
||||
const { post_id, by_user_id } = payload
|
||||
|
||||
if (!by_user_id) {
|
||||
throw new Error("by_user_id not provided")
|
||||
}
|
||||
|
||||
const post = await Post.findById(post_id)
|
||||
|
||||
if (!post) {
|
||||
throw new Error("Post not found")
|
||||
}
|
||||
|
||||
const hasAdmin = await hasAdmin(by_user_id)
|
||||
|
||||
// check if user is the owner of the post
|
||||
if (post.user_id !== by_user_id && !hasAdmin) {
|
||||
throw new Error("You are not allowed to delete this post")
|
||||
}
|
||||
|
||||
await post.remove()
|
||||
global.wsInterface.io.emit(`post.delete`, post_id)
|
||||
|
||||
return post.toObject()
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { Post, User } from "../../../models"
|
||||
|
||||
export default async (payload) => {
|
||||
let {
|
||||
post_id,
|
||||
} = payload
|
||||
|
||||
if (!post_id) {
|
||||
throw new Error("post_id not provided")
|
||||
}
|
||||
|
||||
let post = await Post.findById(post_id).catch(() => false)
|
||||
|
||||
if (!post) {
|
||||
throw new Error("Post not found")
|
||||
}
|
||||
|
||||
let user = await User.findById(post.user_id).catch(() => false)
|
||||
|
||||
if (!user) {
|
||||
user = {
|
||||
username: "Deleted user",
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...post.toObject(),
|
||||
user,
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import { Post, User } from "../../../models"
|
||||
|
||||
export default async (payload) => {
|
||||
let {
|
||||
from_user_id,
|
||||
for_user_id,
|
||||
feedTrimIndex = 0,
|
||||
feedLimit = 20,
|
||||
} = payload
|
||||
|
||||
let query = {}
|
||||
|
||||
if (from_user_id) {
|
||||
query.user_id = from_user_id
|
||||
}
|
||||
|
||||
// make sure that sort by date descending
|
||||
// trim index is used to get the last n posts
|
||||
let posts = await Post.find(query)
|
||||
.sort({ created_at: -1 })
|
||||
.skip(feedTrimIndex)
|
||||
.limit(feedLimit)
|
||||
|
||||
// fetch and add user data to each post
|
||||
posts = posts.map(async (post, index) => {
|
||||
const user = await User.findById(post.user_id)
|
||||
|
||||
if (feedTrimIndex > 0) {
|
||||
index = Number(feedTrimIndex) + Number(index)
|
||||
}
|
||||
|
||||
return {
|
||||
...post.toObject(),
|
||||
user: user.toObject(),
|
||||
key: index,
|
||||
}
|
||||
})
|
||||
|
||||
posts = await Promise.all(posts)
|
||||
|
||||
return posts
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
export { default as CreatePost } from "./createPost"
|
||||
export { default as ToogleLike } from "./toogleLike"
|
||||
export { default as GetPostsFeed } from "./getPostsFeed"
|
||||
export { default as GetPostData } from "./getPostData"
|
||||
export { default as DeletePost } from "./deletePost"
|
||||
|
||||
export { default as ModifyPostData } from "./modifyPostData"
|
@ -0,0 +1,23 @@
|
||||
import { Post } from "../../../models"
|
||||
import lodash from "lodash"
|
||||
|
||||
export default async (post, modification) => {
|
||||
if (typeof post === "string") {
|
||||
post = await Post.findById(post).catch(() => false)
|
||||
}
|
||||
|
||||
if (!post) {
|
||||
throw new Error("Cannot modify post data: post not found")
|
||||
}
|
||||
|
||||
if (typeof modification === "object") {
|
||||
post = lodash.merge(post, modification)
|
||||
}
|
||||
|
||||
await post.save()
|
||||
|
||||
global.wsInterface.io.emit(`post.dataUpdate`, post.toObject())
|
||||
global.wsInterface.io.emit(`post.dataUpdate.${post._id}`, post.toObject())
|
||||
|
||||
return post
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import { Post, User } from "../../../models"
|
||||
import modifyPostData from "./modifyPostData"
|
||||
|
||||
export default async (payload) => {
|
||||
let { post_id, user_id, to } = payload
|
||||
|
||||
const post = await Post.findById(post_id).catch(() => false)
|
||||
const userData = await User.findById(user_id).catch(() => false)
|
||||
|
||||
if (!post) {
|
||||
throw new Error("Post not found")
|
||||
}
|
||||
|
||||
if (!userData) {
|
||||
throw new Error("User not found")
|
||||
}
|
||||
|
||||
if (typeof to === "undefined") {
|
||||
to = !post.likes.includes(user_id)
|
||||
}
|
||||
|
||||
if (to) {
|
||||
post.likes.push(user_id)
|
||||
} else {
|
||||
post.likes = post.likes.filter((id) => id !== user_id)
|
||||
}
|
||||
|
||||
await modifyPostData(post, { likes: post.likes })
|
||||
|
||||
global.wsInterface.io.emit(`post.${to ? "like" : "unlike"}`, {
|
||||
...post.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.${to ? "like" : "unlike"}.${post.user_id}`, {
|
||||
...post.toObject(),
|
||||
user: userData.toObject(),
|
||||
})
|
||||
global.wsInterface.io.emit(`post.${to ? "like" : "unlike"}.${post_id}`, post.toObject().likes)
|
||||
|
||||
return post.toObject()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user