diff --git a/packages/server/package.json b/packages/server/package.json index 522b4389..100ac0d7 100755 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -21,7 +21,7 @@ "formidable": "^2.1.1", "jimp": "^0.16.2", "jsonwebtoken": "^9.0.0", - "linebridge": "0.15.2", + "linebridge": "0.15.4", "luxon": "^3.2.1", "minio": "^7.0.32", "moment": "^2.29.4", diff --git a/packages/server/src/api.js b/packages/server/src/api.js index 43e0c4d0..29737cc7 100755 --- a/packages/server/src/api.js +++ b/packages/server/src/api.js @@ -47,7 +47,7 @@ export default class API { jwtStrategy = global.jwtStrategy = { jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), - secretOrKey: this.server.oskid, + secretOrKey: this.server.server_token, algorithms: ["sha1", "RS256", "HS256"], expiresIn: process.env.signLifetime ?? "1h", enforceRegenerationTokenExpiration: false, diff --git a/packages/server/src/controllers/BadgesController/endpoints/getUserBadges.js b/packages/server/src/controllers/BadgesController/endpoints/getUserBadges.js index 3065171f..03128b54 100644 --- a/packages/server/src/controllers/BadgesController/endpoints/getUserBadges.js +++ b/packages/server/src/controllers/BadgesController/endpoints/getUserBadges.js @@ -2,9 +2,11 @@ import { User, Badge } from "@models" export default { method: "GET", - route: "/user", + route: "/user/:user_id", fn: async (req, res) => { - const user = await User.findOne({ _id: req.query.user_id ?? req.user._id }) + const user = await User.findOne({ + _id: req.params.user_id, + }) if (!user) { return res.status(404).json({ error: "User not found" }) diff --git a/packages/server/src/controllers/CommentsController/endpoints/createPostComment.js b/packages/server/src/controllers/CommentsController/endpoints/createPostComment.js index 82b41aa8..73edaf50 100644 --- a/packages/server/src/controllers/CommentsController/endpoints/createPostComment.js +++ b/packages/server/src/controllers/CommentsController/endpoints/createPostComment.js @@ -1,9 +1,10 @@ import { Schematized } from "@lib" -import newComment from "../methods/newComment" +import newComment from "../services/newComment" export default { method: "POST", route: "/post/:post_id", + middlewares: ["withAuthentication"], fn: Schematized({ required: ["message"], select: ["message"], diff --git a/packages/server/src/controllers/CommentsController/endpoints/deletePostComment.js b/packages/server/src/controllers/CommentsController/endpoints/deletePostComment.js index c87c3ca3..a69e31e4 100644 --- a/packages/server/src/controllers/CommentsController/endpoints/deletePostComment.js +++ b/packages/server/src/controllers/CommentsController/endpoints/deletePostComment.js @@ -1,4 +1,4 @@ -import deleteComment from "../methods/deleteComment" +import deleteComment from "../services/deleteComment" export default { method: "DELETE", diff --git a/packages/server/src/controllers/CommentsController/endpoints/getPostComments.js b/packages/server/src/controllers/CommentsController/endpoints/getPostComments.js index 0f3ae4e6..c675877c 100644 --- a/packages/server/src/controllers/CommentsController/endpoints/getPostComments.js +++ b/packages/server/src/controllers/CommentsController/endpoints/getPostComments.js @@ -1,4 +1,4 @@ -import getComments from "../methods/getComments" +import getComments from "../services/getComments" export default { method: "GET", diff --git a/packages/server/src/controllers/CommentsController/methods/deleteComment.js b/packages/server/src/controllers/CommentsController/services/deleteComment.js similarity index 80% rename from packages/server/src/controllers/CommentsController/methods/deleteComment.js rename to packages/server/src/controllers/CommentsController/services/deleteComment.js index 3dc371d6..99152948 100755 --- a/packages/server/src/controllers/CommentsController/methods/deleteComment.js +++ b/packages/server/src/controllers/CommentsController/services/deleteComment.js @@ -26,8 +26,8 @@ export default async (payload) => { await comment.delete() - global.wsInterface.io.emit(`comment.delete.${comment_id}`) - global.wsInterface.io.emit(`post.delete.comment.${comment.parent_id.toString()}`, comment_id) + global.websocket_instance.io.emit(`comment.delete.${comment_id}`) + global.websocket_instance.io.emit(`post.delete.comment.${comment.parent_id.toString()}`, comment_id) return comment } diff --git a/packages/server/src/controllers/CommentsController/methods/getComments.js b/packages/server/src/controllers/CommentsController/services/getComments.js similarity index 100% rename from packages/server/src/controllers/CommentsController/methods/getComments.js rename to packages/server/src/controllers/CommentsController/services/getComments.js diff --git a/packages/server/src/controllers/CommentsController/methods/newComment.js b/packages/server/src/controllers/CommentsController/services/newComment.js similarity index 83% rename from packages/server/src/controllers/CommentsController/methods/newComment.js rename to packages/server/src/controllers/CommentsController/services/newComment.js index cdd47aca..2260f526 100755 --- a/packages/server/src/controllers/CommentsController/methods/newComment.js +++ b/packages/server/src/controllers/CommentsController/services/newComment.js @@ -25,12 +25,12 @@ export default async (payload) => { const userData = await User.findById(user_id) - global.wsInterface.io.emit(`comment.new.${parent_id}`, { + global.websocket_instance.io.emit(`comment.new.${parent_id}`, { ...comment.toObject(), user: userData.toObject(), }) - global.wsInterface.io.emit(`post.new.comment.${parent_id}`, { + global.websocket_instance.io.emit(`post.new.comment.${parent_id}`, { ...comment.toObject(), user: userData.toObject(), }) diff --git a/packages/server/src/controllers/FollowController/endpoints/getFollowStatus.js b/packages/server/src/controllers/FollowController/endpoints/getFollowStatus.js index 65738433..e40f65bd 100644 --- a/packages/server/src/controllers/FollowController/endpoints/getFollowStatus.js +++ b/packages/server/src/controllers/FollowController/endpoints/getFollowStatus.js @@ -2,7 +2,7 @@ import { UserFollow } from "@models" export default { method: "GET", - route: "/user/:user_id/is_followed", + route: "/user/:user_id", middlewares: ["withAuthentication"], fn: async (req, res) => { const isFollowed = await UserFollow.findOne({ diff --git a/packages/server/src/controllers/FollowController/endpoints/getUserFollowers.js b/packages/server/src/controllers/FollowController/endpoints/getUserFollowers.js index 0fe7e972..c371864b 100644 --- a/packages/server/src/controllers/FollowController/endpoints/getUserFollowers.js +++ b/packages/server/src/controllers/FollowController/endpoints/getUserFollowers.js @@ -1,4 +1,4 @@ -import { User, UserFollow } from "@lib" +import { User, UserFollow } from "@models" export default { method: "GET", diff --git a/packages/server/src/controllers/FollowController/services/followUser.js b/packages/server/src/controllers/FollowController/services/followUser.js index 985106a3..03db4f65 100644 --- a/packages/server/src/controllers/FollowController/services/followUser.js +++ b/packages/server/src/controllers/FollowController/services/followUser.js @@ -30,10 +30,10 @@ export default async (payload) => { await newFollow.save() - global.wsInterface.io.emit(`user.follow`, { + global.websocket_instance.io.emit(`user.follow`, { ...user.toObject(), }) - global.wsInterface.io.emit(`user.follow.${payload.user_id}`, { + global.websocket_instance.io.emit(`user.follow.${payload.user_id}`, { ...user.toObject(), }) diff --git a/packages/server/src/controllers/FollowController/services/unfollowUser.js b/packages/server/src/controllers/FollowController/services/unfollowUser.js index 9736d674..13bc666c 100644 --- a/packages/server/src/controllers/FollowController/services/unfollowUser.js +++ b/packages/server/src/controllers/FollowController/services/unfollowUser.js @@ -25,10 +25,10 @@ export default async (payload) => { await follow.remove() - global.wsInterface.io.emit(`user.unfollow`, { + global.websocket_instance.io.emit(`user.unfollow`, { ...user.toObject(), }) - global.wsInterface.io.emit(`user.unfollow.${payload.user_id}`, { + global.websocket_instance.io.emit(`user.unfollow.${payload.user_id}`, { ...user.toObject(), }) diff --git a/packages/server/src/controllers/PostsController/endpoints/createPost.js b/packages/server/src/controllers/PostsController/endpoints/createPost.js index 4686cc18..7ad91379 100644 --- a/packages/server/src/controllers/PostsController/endpoints/createPost.js +++ b/packages/server/src/controllers/PostsController/endpoints/createPost.js @@ -1,5 +1,5 @@ import { Schematized } from "@lib" -import { CreatePost } from "../methods" +import { CreatePost } from "../services" export default { method: "POST", diff --git a/packages/server/src/controllers/PostsController/endpoints/deletePost.js b/packages/server/src/controllers/PostsController/endpoints/deletePost.js index 39015fec..228b2486 100644 --- a/packages/server/src/controllers/PostsController/endpoints/deletePost.js +++ b/packages/server/src/controllers/PostsController/endpoints/deletePost.js @@ -1,4 +1,4 @@ -import { DeletePost } from "../methods" +import { DeletePost } from "../services" export default { method: "DELETE", diff --git a/packages/server/src/controllers/PostsController/endpoints/explorePosts.js b/packages/server/src/controllers/PostsController/endpoints/explorePosts.js index f4ff9e35..b5db54c2 100644 --- a/packages/server/src/controllers/PostsController/endpoints/explorePosts.js +++ b/packages/server/src/controllers/PostsController/endpoints/explorePosts.js @@ -1,5 +1,5 @@ import { Schematized } from "@lib" -import { GetPostData } from "../methods" +import { GetPostData } from "../services" export default { method: "GET", diff --git a/packages/server/src/controllers/PostsController/endpoints/getPostData.js b/packages/server/src/controllers/PostsController/endpoints/getPostData.js index 1b24803a..649fa54a 100644 --- a/packages/server/src/controllers/PostsController/endpoints/getPostData.js +++ b/packages/server/src/controllers/PostsController/endpoints/getPostData.js @@ -1,8 +1,8 @@ -import { GetPostData } from "../methods" +import { GetPostData } from "../services" export default { method: "GET", - route: "/:post_id", + route: "/post/:post_id", middlewares: ["withOptionalAuthentication"], fn: async (req, res) => { let post = await GetPostData({ diff --git a/packages/server/src/controllers/PostsController/endpoints/getPostFromUser.js b/packages/server/src/controllers/PostsController/endpoints/getPostFromUser.js index 96bec9ae..bce72f75 100644 --- a/packages/server/src/controllers/PostsController/endpoints/getPostFromUser.js +++ b/packages/server/src/controllers/PostsController/endpoints/getPostFromUser.js @@ -1,4 +1,4 @@ -import { GetPostData } from "../methods" +import { GetPostData } from "../services" export default { method: "GET", diff --git a/packages/server/src/controllers/PostsController/endpoints/savedPosts.js b/packages/server/src/controllers/PostsController/endpoints/savedPosts.js index e9f9f29d..d4bd4f3a 100644 --- a/packages/server/src/controllers/PostsController/endpoints/savedPosts.js +++ b/packages/server/src/controllers/PostsController/endpoints/savedPosts.js @@ -1,5 +1,5 @@ import { Schematized } from "@lib" -import { GetPostData } from "../methods" +import { GetPostData } from "../services" export default { method: "GET", diff --git a/packages/server/src/controllers/PostsController/endpoints/toogleLike.js b/packages/server/src/controllers/PostsController/endpoints/toogleLike.js index 9b50b035..2e26e7a6 100644 --- a/packages/server/src/controllers/PostsController/endpoints/toogleLike.js +++ b/packages/server/src/controllers/PostsController/endpoints/toogleLike.js @@ -1,8 +1,8 @@ import { Schematized } from "@lib" -import { ToogleLike } from "../methods" +import { ToogleLike } from "../services" export default { - method: "GET", + method: "POST", route: "/:post_id/toogle_like", middlewares: ["withAuthentication"], fn: Schematized({ diff --git a/packages/server/src/controllers/PostsController/endpoints/toogleSave.js b/packages/server/src/controllers/PostsController/endpoints/toogleSave.js index 25b180db..c8ce2d0d 100644 --- a/packages/server/src/controllers/PostsController/endpoints/toogleSave.js +++ b/packages/server/src/controllers/PostsController/endpoints/toogleSave.js @@ -1,4 +1,4 @@ -import { ToogleSavePost } from "../methods" +import { ToogleSavePost } from "../services" export default { method: "POST", diff --git a/packages/server/src/controllers/PostsController/methods/createPost.js b/packages/server/src/controllers/PostsController/services/createPost.js similarity index 90% rename from packages/server/src/controllers/PostsController/methods/createPost.js rename to packages/server/src/controllers/PostsController/services/createPost.js index 31811370..2c8ecdc3 100755 --- a/packages/server/src/controllers/PostsController/methods/createPost.js +++ b/packages/server/src/controllers/PostsController/services/createPost.js @@ -36,8 +36,8 @@ export default async (payload) => { const resultPost = await getPostData({ post_id: post._id.toString() }) - global.wsInterface.io.emit(`post.new`, resultPost) - global.wsInterface.io.emit(`post.new.${post.user_id}`, resultPost) + global.websocket_instance.io.emit(`post.new`, resultPost) + global.websocket_instance.io.emit(`post.new.${post.user_id}`, resultPost) // push to background job to check if is NSFW flagNsfwByAttachments(post._id.toString()) diff --git a/packages/server/src/controllers/PostsController/methods/deletePost.js b/packages/server/src/controllers/PostsController/services/deletePost.js similarity index 92% rename from packages/server/src/controllers/PostsController/methods/deletePost.js rename to packages/server/src/controllers/PostsController/services/deletePost.js index bf8ac426..51903f1c 100755 --- a/packages/server/src/controllers/PostsController/methods/deletePost.js +++ b/packages/server/src/controllers/PostsController/services/deletePost.js @@ -27,7 +27,7 @@ export default async (payload) => { } await post.remove() - global.wsInterface.io.emit(`post.delete`, post_id) + global.websocket_instance.io.emit(`post.delete`, post_id) return post.toObject() } \ No newline at end of file diff --git a/packages/server/src/controllers/PostsController/methods/flagNsfwByAttachments.js b/packages/server/src/controllers/PostsController/services/flagNsfwByAttachments.js similarity index 100% rename from packages/server/src/controllers/PostsController/methods/flagNsfwByAttachments.js rename to packages/server/src/controllers/PostsController/services/flagNsfwByAttachments.js diff --git a/packages/server/src/controllers/PostsController/methods/getPostData.js b/packages/server/src/controllers/PostsController/services/getPostData.js similarity index 92% rename from packages/server/src/controllers/PostsController/methods/getPostData.js rename to packages/server/src/controllers/PostsController/services/getPostData.js index 912836ff..044169fa 100755 --- a/packages/server/src/controllers/PostsController/methods/getPostData.js +++ b/packages/server/src/controllers/PostsController/services/getPostData.js @@ -1,5 +1,5 @@ -import { Post, User, Comment, SavedPost } from "../../../models" -import fullfillPostsData from "../../../utils/fullfillPostsData" +import { Post, SavedPost } from "@models" +import fullfillPostsData from "@utils/fullfillPostsData" export default async (payload) => { let { diff --git a/packages/server/src/controllers/PostsController/methods/index.js b/packages/server/src/controllers/PostsController/services/index.js similarity index 100% rename from packages/server/src/controllers/PostsController/methods/index.js rename to packages/server/src/controllers/PostsController/services/index.js diff --git a/packages/server/src/controllers/PostsController/methods/modifyPostData.js b/packages/server/src/controllers/PostsController/services/modifyPostData.js similarity index 82% rename from packages/server/src/controllers/PostsController/methods/modifyPostData.js rename to packages/server/src/controllers/PostsController/services/modifyPostData.js index fe69fe93..05173877 100755 --- a/packages/server/src/controllers/PostsController/methods/modifyPostData.js +++ b/packages/server/src/controllers/PostsController/services/modifyPostData.js @@ -24,8 +24,8 @@ export default async (post_id, modification) => { } } - global.wsInterface.io.emit(`post.dataUpdate`, post) - global.wsInterface.io.emit(`post.dataUpdate.${post_id._id}`, post) + global.websocket_instance.io.emit(`post.dataUpdate`, post) + global.websocket_instance.io.emit(`post.dataUpdate.${post_id._id}`, post) return post } \ No newline at end of file diff --git a/packages/server/src/controllers/PostsController/methods/toogleLike.js b/packages/server/src/controllers/PostsController/services/toogleLike.js similarity index 69% rename from packages/server/src/controllers/PostsController/methods/toogleLike.js rename to packages/server/src/controllers/PostsController/services/toogleLike.js index 0515165f..1ca6d3a1 100755 --- a/packages/server/src/controllers/PostsController/methods/toogleLike.js +++ b/packages/server/src/controllers/PostsController/services/toogleLike.js @@ -23,9 +23,9 @@ export default async (payload) => { post = await modifyPostData(post._id, { likes: post.likes }) - global.wsInterface.io.emit(`post.${to ? "like" : "unlike"}`, post) - global.wsInterface.io.emit(`post.${to ? "like" : "unlike"}.${post.user_id}`, post) - global.wsInterface.io.emit(`post.${to ? "like" : "unlike"}.${post_id}`, post) + global.websocket_instance.io.emit(`post.${to ? "like" : "unlike"}`, post) + global.websocket_instance.io.emit(`post.${to ? "like" : "unlike"}.${post.user_id}`, post) + global.websocket_instance.io.emit(`post.${to ? "like" : "unlike"}.${post_id}`, post) return post } \ No newline at end of file diff --git a/packages/server/src/controllers/PostsController/methods/tooglePostSave.js b/packages/server/src/controllers/PostsController/services/tooglePostSave.js similarity index 100% rename from packages/server/src/controllers/PostsController/methods/tooglePostSave.js rename to packages/server/src/controllers/PostsController/services/tooglePostSave.js diff --git a/packages/server/src/controllers/RolesController/index.js b/packages/server/src/controllers/RolesController/index.js index e0b7864f..628a27da 100755 --- a/packages/server/src/controllers/RolesController/index.js +++ b/packages/server/src/controllers/RolesController/index.js @@ -15,19 +15,19 @@ export default class RolesController extends Controller { return res.json(roles) }), - "/user_roles": { + "/roles/self": { middlewares: ["withAuthentication"], - fn: Schematized({ - select: ["username"], - }, async (req, res) => { - const user = await User.findOne(req.selection) + fn: async (req, res) => { + const user = await User.findOne({ + _id: req.user._id.toString(), + }) if (!user) { return res.status(404).json({ error: "No user founded" }) } return res.json(user.roles) - }) + } }, }, diff --git a/packages/server/src/controllers/SessionController/endpoints/deleteSelfSession.js b/packages/server/src/controllers/SessionController/endpoints/deleteCurrentSession.js similarity index 81% rename from packages/server/src/controllers/SessionController/endpoints/deleteSelfSession.js rename to packages/server/src/controllers/SessionController/endpoints/deleteCurrentSession.js index 4801c330..86e36f38 100644 --- a/packages/server/src/controllers/SessionController/endpoints/deleteSelfSession.js +++ b/packages/server/src/controllers/SessionController/endpoints/deleteCurrentSession.js @@ -2,14 +2,14 @@ import { Session } from "@models" export default { method: "DELETE", - route: "/", + route: "/current", middlewares: ["withAuthentication"], fn: async (req, res) => { - const { token } = req.body + const token = req.jwtToken const user_id = req.user._id.toString() if (typeof token === "undefined") { - return res.status(400).json("No token provided") + return res.status(400).json("Cannot access to token") } const session = await Session.findOneAndDelete({ user_id, token }) diff --git a/packages/server/src/controllers/StatusController/endpoints/getConnectedFollowedUsers.js b/packages/server/src/controllers/StatusController/endpoints/getConnectedFollowedUsers.js new file mode 100644 index 00000000..335ad726 --- /dev/null +++ b/packages/server/src/controllers/StatusController/endpoints/getConnectedFollowedUsers.js @@ -0,0 +1,16 @@ +import { Endpoint } from "linebridge/dist/server" +import getConnectedUsersFollowing from "../services/getConnectedUsersFollowing" + +export default class GetConnectedFollowedUsers extends Endpoint { + static method = "GET" + static route = "/connected/following" + static middlewares = ["withAuthentication"] + + async fn(req, res) { + const users = await getConnectedUsersFollowing({ + from_user_id: req.user._id.toString(), + }) + + return res.json(users) + } +} \ No newline at end of file diff --git a/packages/server/src/controllers/StatusController/index.js b/packages/server/src/controllers/StatusController/index.js new file mode 100644 index 00000000..6532ba3b --- /dev/null +++ b/packages/server/src/controllers/StatusController/index.js @@ -0,0 +1,9 @@ +import { Controller } from "linebridge/dist/server" +import generateEndpointsFromDir from "linebridge/dist/server/lib/generateEndpointsFromDir" + +export default class StatusController extends Controller { + static refName = "StatusController" + static useRoute = "/status" + + httpEndpoints = generateEndpointsFromDir(__dirname + "/endpoints") +} \ No newline at end of file diff --git a/packages/server/src/controllers/UserController/methods/getConnectedUsersFollowing.js b/packages/server/src/controllers/StatusController/services/getConnectedUsersFollowing.js similarity index 86% rename from packages/server/src/controllers/UserController/methods/getConnectedUsersFollowing.js rename to packages/server/src/controllers/StatusController/services/getConnectedUsersFollowing.js index ea7fe388..3d76aed0 100755 --- a/packages/server/src/controllers/UserController/methods/getConnectedUsersFollowing.js +++ b/packages/server/src/controllers/StatusController/services/getConnectedUsersFollowing.js @@ -12,7 +12,7 @@ export default async (payload = {}) => { const connectedUsers = [] following.forEach((follow) => { - const connectedClient = global.wsInterface.clients.find((client) => { + const connectedClient = global.websocket_instance.clients.find((client) => { return client.user_id === follow.to }) diff --git a/packages/server/src/controllers/StreamingController/endpoints/getStreamAddresses.js b/packages/server/src/controllers/StreamingController/endpoints/getStreamAddresses.js index 55c8a670..6db90d97 100644 --- a/packages/server/src/controllers/StreamingController/endpoints/getStreamAddresses.js +++ b/packages/server/src/controllers/StreamingController/endpoints/getStreamAddresses.js @@ -1,11 +1,11 @@ export default { method: "GET", - route: "/stream/addresses", + route: "/streaming/addresses", middlewares: ["withOptionalAuthentication"], fn: async (req, res) => { const addresses = { - api: process.env.STREAMING_INGEST_SERVER, - ingest: process.env.STREAMING_API_SERVER, + api: process.env.STREAMING_API_SERVER, + ingest: process.env.STREAMING_INGEST_SERVER, } if (req.user) { diff --git a/packages/server/src/controllers/StreamingController/endpoints/getStreamInfo.js b/packages/server/src/controllers/StreamingController/endpoints/getStreamInfo.js index bb111be2..0c0f7452 100644 --- a/packages/server/src/controllers/StreamingController/endpoints/getStreamInfo.js +++ b/packages/server/src/controllers/StreamingController/endpoints/getStreamInfo.js @@ -14,11 +14,11 @@ export default { } if (!user_id) { - user_id = await User.findOne({ + const user = await User.findOne({ username: req.query.username, }) - user_id = user_id["_id"].toString() + user_id = user._id.toString() } let info = await StreamingInfo.findOne({ @@ -33,19 +33,6 @@ export default { await info.save() } - const category = await StreamingCategory.findOne({ - key: info.category - }).catch((err) => { - console.error(err) - return {} - }) ?? {} - - return res.json({ - ...info.toObject(), - ["category"]: { - key: category?.key ?? "unknown", - label: category?.label ?? "Unknown", - } - }) + return res.json(info.toObject()) } } \ No newline at end of file diff --git a/packages/server/src/controllers/StreamingController/endpoints/getStreamingCategories.js b/packages/server/src/controllers/StreamingController/endpoints/getStreamingCategories.js index 63d601f6..4ca44be2 100644 --- a/packages/server/src/controllers/StreamingController/endpoints/getStreamingCategories.js +++ b/packages/server/src/controllers/StreamingController/endpoints/getStreamingCategories.js @@ -6,6 +6,12 @@ export default { fn: async (req, res) => { const categories = await StreamingCategory.find() + if (req.query.key) { + const category = categories.find((category) => category.key === req.query.key) + + return res.json(category) + } + return res.json(categories) } } \ No newline at end of file diff --git a/packages/server/src/controllers/StreamingController/endpoints/getStreams.js b/packages/server/src/controllers/StreamingController/endpoints/getStreams.js index cdd3d44c..2b4004b5 100644 --- a/packages/server/src/controllers/StreamingController/endpoints/getStreams.js +++ b/packages/server/src/controllers/StreamingController/endpoints/getStreams.js @@ -6,6 +6,18 @@ export default { fn: async (req, res) => { const remoteStreams = await fetchStreamsFromAPI() + if (req.query.username) { + const stream = remoteStreams.find((stream) => stream.username === req.query.username) + + if (!stream) { + return res.status(404).json({ + error: "Stream not found" + }) + } + + return res.json(stream) + } + return res.json(remoteStreams) } } \ No newline at end of file diff --git a/packages/server/src/controllers/StreamingController/endpoints/handleStreamPublish.js b/packages/server/src/controllers/StreamingController/endpoints/handleStreamPublish.js index ccc4e075..c5203304 100644 --- a/packages/server/src/controllers/StreamingController/endpoints/handleStreamPublish.js +++ b/packages/server/src/controllers/StreamingController/endpoints/handleStreamPublish.js @@ -19,9 +19,9 @@ export default { }) if (streaming) { - global.wsInterface.io.emit(`streaming.new`, streaming) + global.websocket_instance.io.emit(`streaming.new`, streaming) - global.wsInterface.io.emit(`streaming.new.${streaming.username}`, streaming) + global.websocket_instance.io.emit(`streaming.new.${streaming.username}`, streaming) return res.json({ code: 0, diff --git a/packages/server/src/controllers/StreamingController/endpoints/handleStreamUnpublish.js b/packages/server/src/controllers/StreamingController/endpoints/handleStreamUnpublish.js index bcdfe830..bee1b475 100644 --- a/packages/server/src/controllers/StreamingController/endpoints/handleStreamUnpublish.js +++ b/packages/server/src/controllers/StreamingController/endpoints/handleStreamUnpublish.js @@ -13,9 +13,9 @@ export default { }) if (streaming) { - global.wsInterface.io.emit(`streaming.end`, streaming) + global.websocket_instance.io.emit(`streaming.end`, streaming) - global.wsInterface.io.emit(`streaming.end.${streaming.username}`, streaming) + global.websocket_instance.io.emit(`streaming.end.${streaming.username}`, streaming) return res.json({ code: 0, diff --git a/packages/server/src/controllers/StreamingController/services/fetchStreamsFromAPI.js b/packages/server/src/controllers/StreamingController/services/fetchStreamsFromAPI.js index 7e13c855..6241ee06 100644 --- a/packages/server/src/controllers/StreamingController/services/fetchStreamsFromAPI.js +++ b/packages/server/src/controllers/StreamingController/services/fetchStreamsFromAPI.js @@ -1,7 +1,7 @@ import axios from "axios" import lodash from "lodash" -import { StreamingCategory } from "@models" +import { StreamingCategory, StreamingInfo } from "@models" import generateStreamDataFromStreamingKey from "./generateStreamDataFromStreamingKey" const streamingServerAPIAddress = process.env.STREAMING_API_SERVER ?? "" diff --git a/packages/server/src/controllers/StreamingController/services/generateStreamDataFromStreamingKey.js b/packages/server/src/controllers/StreamingController/services/generateStreamDataFromStreamingKey.js index 85233cef..843db2a6 100644 --- a/packages/server/src/controllers/StreamingController/services/generateStreamDataFromStreamingKey.js +++ b/packages/server/src/controllers/StreamingController/services/generateStreamDataFromStreamingKey.js @@ -1,5 +1,7 @@ import { StreamingKey } from "@models" +const streamingServerAPIUri = process.env.STREAMING_API_SERVER ? `${process.env.STREAMING_API_SERVER.startsWith("https") ? "https" : "http"}://${process.env.STREAMING_API_SERVER.split("://")[1]}` : "Not available" + export default async (key) => { // generate a stream from a streamkey const streamingKey = await StreamingKey.findOne({ @@ -12,9 +14,9 @@ export default async (key) => { user_id: streamingKey.user_id, username: streamingKey.username, sources: { - rtmp: `${streamingIngestServer}/live/${streamingKey.username}`, - hls: `${streamingServerAPIAddress}/live/${streamingKey.username}/src.m3u8`, - flv: `${streamingServerAPIAddress}/live/${streamingKey.username}/src.flv`, + rtmp: `${process.env.STREAMING_INGEST_SERVER}/live/${streamingKey.username}`, + hls: `${streamingServerAPIUri}/live/${streamingKey.username}/src.m3u8`, + flv: `${streamingServerAPIUri}/live/${streamingKey.username}/src.flv`, } } diff --git a/packages/server/src/controllers/StreamingController/services/handleStreamInfoUpdate.js b/packages/server/src/controllers/StreamingController/services/handleStreamInfoUpdate.js index 99ea74a8..0b581d24 100644 --- a/packages/server/src/controllers/StreamingController/services/handleStreamInfoUpdate.js +++ b/packages/server/src/controllers/StreamingController/services/handleStreamInfoUpdate.js @@ -34,7 +34,7 @@ export default async (payload) => { await info.save() - global.wsInterface.io.emit(`streaming.info_update.${payload.user_id}`, info) + global.websocket_instance.io.emit(`streaming.info_update.${payload.user_id}`, info) return info } \ No newline at end of file diff --git a/packages/server/src/controllers/UserController/endpoints/getConnectedFollowingUsers.js b/packages/server/src/controllers/UserController/endpoints/getConnectedFollowingUsers.js index 286599bd..4e488d11 100644 --- a/packages/server/src/controllers/UserController/endpoints/getConnectedFollowingUsers.js +++ b/packages/server/src/controllers/UserController/endpoints/getConnectedFollowingUsers.js @@ -1,8 +1,8 @@ -import getConnectedUsersFollowing from "../methods/getConnectedUsersFollowing" +import getConnectedUsersFollowing from "../services/getConnectedUsersFollowing" export default { method: "GET", - route: "/connected_following_users", + route: "/connected/followers", middlewares: ["withAuthentication"], fn: async (req, res) => { const users = await getConnectedUsersFollowing({ diff --git a/packages/server/src/controllers/UserController/endpoints/getPublicData.js b/packages/server/src/controllers/UserController/endpoints/getPublicData.js deleted file mode 100644 index fcb43a52..00000000 --- a/packages/server/src/controllers/UserController/endpoints/getPublicData.js +++ /dev/null @@ -1,39 +0,0 @@ -import lodash from "lodash" -import { User } from "@models" - -const AllowedAnonPublicGetters = [ - "_id", - "username", - "fullName", - "avatar", - "roles" -] - -export default { - method: "GET", - route: "/public_data", - middlewares: ["withOptionalAuthentication"], - fn: async (req, res) => { - let user = req.query?.username ?? req.user.username - - if (!user) { - return res.status(400).json({ - error: "No user provided", - }) - } - - user = await User.findOne({ - username: user, - }).catch(() => null) - - if (!user) { - return res.json({ - user: null, - }) - } - - user = lodash.pick(user, AllowedAnonPublicGetters) - - return res.json(user) - } -} \ No newline at end of file diff --git a/packages/server/src/controllers/UserController/endpoints/getUserData.js b/packages/server/src/controllers/UserController/endpoints/getUserData.js index dce8c3d9..e72d188c 100644 --- a/packages/server/src/controllers/UserController/endpoints/getUserData.js +++ b/packages/server/src/controllers/UserController/endpoints/getUserData.js @@ -1,14 +1,35 @@ +import lodash from "lodash" +import { User } from "@models" + +const publicGetters = [ + "_id", + "username", + "fullName", + "avatar", + "roles", + "badges", + "cover", + "verified", + "description", +] + export default { method: "GET", route: "/:user_id/data", middlewares: ["withAuthentication"], fn: async (req, res) => { - let user = await User.findOne(req.params.user_id) + let user = await User.findOne({ + _id: req.params.user_id, + }) if (!user) { return res.status(404).json({ error: "User not exists" }) } + if (req.user._id.toString() !== user._id.toString()) { + user = lodash.pick(user, publicGetters) + } + return res.json(user) } } \ No newline at end of file diff --git a/packages/server/src/controllers/UserController/endpoints/resolveUserIdFromUsername.js b/packages/server/src/controllers/UserController/endpoints/resolveUserIdFromUsername.js new file mode 100644 index 00000000..cfaae163 --- /dev/null +++ b/packages/server/src/controllers/UserController/endpoints/resolveUserIdFromUsername.js @@ -0,0 +1,19 @@ +import { User } from "@models" + +export default { + method: "GET", + route: "/user_id/:username", + middlewares: ["withAuthentication"], + fn: async (req, res) => { + const user = await User.findOne({ username: req.params.username }) + + if (!user) { + return res.status(404).json({ error: "User not exists" }) + } + + return res.json({ + username: user.username, + user_id: user._id, + }) + } +} \ No newline at end of file diff --git a/packages/server/src/controllers/UserController/endpoints/selfDeletePublicName.js b/packages/server/src/controllers/UserController/endpoints/selfDeletePublicName.js index 862a6bb2..954252e9 100644 --- a/packages/server/src/controllers/UserController/endpoints/selfDeletePublicName.js +++ b/packages/server/src/controllers/UserController/endpoints/selfDeletePublicName.js @@ -1,4 +1,4 @@ -import UpdateUserData from "../methods/updateUserData" +import UpdateUserData from "../services/updateUserData" export default { method: "DELETE", @@ -7,7 +7,7 @@ export default { fn: async (req, res) => { const user_id = req.user._id.toString() - UpdateUserData.update({ + UpdateUserData({ user_id: user_id, update: { fullName: undefined diff --git a/packages/server/src/controllers/UserController/endpoints/selfUpdateData.js b/packages/server/src/controllers/UserController/endpoints/selfUpdateData.js index a0fdbe41..a1465fc2 100644 --- a/packages/server/src/controllers/UserController/endpoints/selfUpdateData.js +++ b/packages/server/src/controllers/UserController/endpoints/selfUpdateData.js @@ -1,6 +1,6 @@ import { Schematized } from "@lib" - -import UpdateUserData from "../methods/updateUserData" +import { User } from "@models" +import UpdateUserData from "../services/updateUserData" const AllowedPublicUpdateFields = [ "fullName", @@ -19,7 +19,7 @@ const MaxStringsLengths = { export default { method: "POST", route: "/self/update_data", - middlewares: ["withAuthentication", "roles"], + middlewares: ["withAuthentication"], fn: Schematized({ required: ["update"], select: ["update"], @@ -43,7 +43,20 @@ export default { } }) - UpdateUserData.update({ + // check if email is already in use + if (typeof update.email !== "undefined") { + const user = await User.findOne({ + email: update.email, + }) + + if (user) { + return res.status(400).json({ + error: "Email is already in use", + }) + } + } + + UpdateUserData({ user_id: user_id, update: update, }).then((user) => { diff --git a/packages/server/src/controllers/UserController/endpoints/selfUpdatePassword.js b/packages/server/src/controllers/UserController/endpoints/selfUpdatePassword.js index 70ae4aff..f79c776b 100644 --- a/packages/server/src/controllers/UserController/endpoints/selfUpdatePassword.js +++ b/packages/server/src/controllers/UserController/endpoints/selfUpdatePassword.js @@ -1,7 +1,7 @@ import { Schematized } from "@lib" import { User } from "@models" -import updateUserPassword from "../methods/updateUserPassword" +import updateUserPassword from "../services/updateUserPassword" import bcrypt from "bcrypt" export default { diff --git a/packages/server/src/controllers/UserController/methods/createUser.js b/packages/server/src/controllers/UserController/services/createUser.js similarity index 100% rename from packages/server/src/controllers/UserController/methods/createUser.js rename to packages/server/src/controllers/UserController/services/createUser.js diff --git a/packages/server/src/controllers/UserController/services/getConnectedUsersFollowing.js b/packages/server/src/controllers/UserController/services/getConnectedUsersFollowing.js new file mode 100755 index 00000000..3d76aed0 --- /dev/null +++ b/packages/server/src/controllers/UserController/services/getConnectedUsersFollowing.js @@ -0,0 +1,25 @@ +import { UserFollow } from "@models" + +export default async (payload = {}) => { + const { from_user_id } = payload + + // get all the users that are following + const following = await UserFollow.find({ + user_id: from_user_id, + }) + + // check if following users are connected + const connectedUsers = [] + + following.forEach((follow) => { + const connectedClient = global.websocket_instance.clients.find((client) => { + return client.user_id === follow.to + }) + + if (connectedClient) { + connectedUsers.push(connectedClient.user_id) + } + }) + + return connectedUsers +} \ No newline at end of file diff --git a/packages/server/src/controllers/UserController/methods/updateUserData.js b/packages/server/src/controllers/UserController/services/updateUserData.js similarity index 83% rename from packages/server/src/controllers/UserController/methods/updateUserData.js rename to packages/server/src/controllers/UserController/services/updateUserData.js index ec886b33..0a72aba5 100644 --- a/packages/server/src/controllers/UserController/methods/updateUserData.js +++ b/packages/server/src/controllers/UserController/services/updateUserData.js @@ -22,10 +22,10 @@ export default async (payload) => { await user.save() - global.wsInterface.io.emit(`user.update`, { + global.websocket_instance.io.emit(`user.update`, { ...user.toObject(), }) - global.wsInterface.io.emit(`user.update.${payload.user_id}`, { + global.websocket_instance.io.emit(`user.update.${payload.user_id}`, { ...user.toObject(), }) diff --git a/packages/server/src/controllers/UserController/methods/updateUserPassword.js b/packages/server/src/controllers/UserController/services/updateUserPassword.js similarity index 100% rename from packages/server/src/controllers/UserController/methods/updateUserPassword.js rename to packages/server/src/controllers/UserController/services/updateUserPassword.js diff --git a/packages/server/src/controllers/index.js b/packages/server/src/controllers/index.js index 7cb1cdd7..43bc8f11 100644 --- a/packages/server/src/controllers/index.js +++ b/packages/server/src/controllers/index.js @@ -4,6 +4,7 @@ export { default as UserController } from "./UserController" export { default as AuthController } from "./AuthController" export { default as SessionController } from "./SessionController" +export { default as StatusController } from "./StatusController" export { default as FollowController } from "./FollowController" export { default as PostsController } from "./PostsController" diff --git a/packages/server/src/events/user_connected.js b/packages/server/src/events/user_connected.js index 771f7a2e..eda87f02 100755 --- a/packages/server/src/events/user_connected.js +++ b/packages/server/src/events/user_connected.js @@ -8,7 +8,7 @@ export default async (user_id) => { // send event to ws clients (if are connected) followers.forEach((follow) => { - const connectedClient = global.wsInterface.clients.find((client) => { + const connectedClient = global.websocket_instance.clients.find((client) => { return client.user_id === follow.user_id }) diff --git a/packages/server/src/events/user_disconnected.js b/packages/server/src/events/user_disconnected.js index aca0d317..9706e471 100755 --- a/packages/server/src/events/user_disconnected.js +++ b/packages/server/src/events/user_disconnected.js @@ -8,7 +8,7 @@ export default async (user_id) => { // send event to ws clients (if are connected) followers.forEach((follow) => { - const connectedClient = global.wsInterface.clients.find((client) => { + const connectedClient = global.websocket_instance.clients.find((client) => { return client.user_id === follow.user_id }) diff --git a/packages/server/src/index.js b/packages/server/src/index.js index 2d23a1e7..5de598db 100755 --- a/packages/server/src/index.js +++ b/packages/server/src/index.js @@ -1,5 +1,5 @@ require("dotenv").config() -const crypto = require("node:crypto") +import { webcrypto as crypto } from "crypto" // patches const { Buffer } = require("buffer") diff --git a/packages/server/src/lib/additionsHandler/handlers/essc.js b/packages/server/src/lib/additionsHandler/handlers/essc.js deleted file mode 100755 index 5b850d86..00000000 --- a/packages/server/src/lib/additionsHandler/handlers/essc.js +++ /dev/null @@ -1,11 +0,0 @@ -import { genV1 } from "../../essc" - -export default (obj) => { - obj.essc = genV1({ - type: obj.vaultItemTypeSelector ?? obj.type, - serial: obj.vaultItemSerial ?? obj.serial, - manufacturer: obj.vaultItemManufacturer ?? obj.manufacturer, - }) - - return obj -} \ No newline at end of file diff --git a/packages/server/src/lib/additionsHandler/handlers/vaultItemFlatProperties.js b/packages/server/src/lib/additionsHandler/handlers/vaultItemFlatProperties.js deleted file mode 100755 index 5e5346c3..00000000 --- a/packages/server/src/lib/additionsHandler/handlers/vaultItemFlatProperties.js +++ /dev/null @@ -1,6 +0,0 @@ -export default (obj) => { - return { - ...obj, - ...obj.properties, - } -} \ No newline at end of file diff --git a/packages/server/src/lib/additionsHandler/handlers/vaultItemParser.js b/packages/server/src/lib/additionsHandler/handlers/vaultItemParser.js deleted file mode 100755 index 91f10393..00000000 --- a/packages/server/src/lib/additionsHandler/handlers/vaultItemParser.js +++ /dev/null @@ -1,17 +0,0 @@ -export default (obj) => { - const fixedKeys = { - vaultItemManufacturer: "manufacturer", - vaultItemSerial: "serial", - vaultItemTypeSelector: "type", - vaultItemManufacturedYear: "manufacturedYear", - } - - Object.keys(obj).forEach(key => { - if (fixedKeys[key]) { - obj[fixedKeys[key]] = obj[key] - delete obj[key] - } - }) - - return obj -} \ No newline at end of file diff --git a/packages/server/src/lib/additionsHandler/index.js b/packages/server/src/lib/additionsHandler/index.js deleted file mode 100755 index b4867a50..00000000 --- a/packages/server/src/lib/additionsHandler/index.js +++ /dev/null @@ -1,22 +0,0 @@ -export default async (additions, obj) => { - let query = [] - - if (Array.isArray(additions)) { - query = additions - }else { - query.push(additions) - } - - for await(let addition of query) { - try { - let script = await import(`./handlers/${addition}.js`) - script = script.default || script - - obj = await script(obj) - } catch (error) { - - } - } - - return obj -} \ No newline at end of file diff --git a/packages/server/src/lib/essc/index.js b/packages/server/src/lib/essc/index.js deleted file mode 100755 index aaf41591..00000000 --- a/packages/server/src/lib/essc/index.js +++ /dev/null @@ -1,70 +0,0 @@ -// random 5 digits number -const random5 = () => Math.floor(Math.random() * 90000) + 10000 - -// secure random 5 digits number -const random5Secure = () => { - const random = random5() - return random.toString().padStart(5, '0') -} - -// aa-bbbbb-cccc -//* a: type (2 digits) -//* b: serial (5 digits) -//* c: manufacturer (4 digits) - -const typesNumber = { - "computers-desktop": [1], - "computers-laptop": [2], - "computers-tablet": [3], - "computers-smartphone": [4], - "networking": [5], - "peripherals-printer": [6], - "peripherals-monitor": [7], -} - -export function genV1(params) { - let { type, serial, manufacturer } = params // please in that order - type = type.toLowerCase() - - let str = [] - - // Type parsing - let typeBuf = [] - - if (typeof typesNumber[type] === "undefined") { - typeBuf[0] = 0 - typeBuf[1] = "X" - } else { - typeBuf[0] = typesNumber[type][0] - typeBuf[1] = typesNumber[type][1] ?? "X" - } - - str.push(typeBuf.join("")) - - // Serial parsing - // if serial is not defined, generate a random 4 digits number - if (typeof serial === "undefined") { - str.push(random5().toString()) - } else { - // push last 5 digits of serial, if serial is not 5 digits, pad with 0 - let serialBuf = [] - - serialBuf[0] = serial.slice(-5, -4) ?? "0" - serialBuf[1] = serial.slice(-4, -3) ?? "0" - serialBuf[2] = serial.slice(-3, -2) ?? "0" - serialBuf[3] = serial.slice(-2, -1) ?? "0" - serialBuf[4] = serial.slice(-1) ?? "0" - - str.push(serialBuf.join("")) - } - - // Manufacturer parsing - // abreviate manufacturer name to 4 letters - if (typeof manufacturer === "undefined") { - str.push("GENR") - } else { - str.push(manufacturer.slice(0, 4).toUpperCase()) - } - - return str.join("-") -} \ No newline at end of file diff --git a/packages/server/src/lib/index.js b/packages/server/src/lib/index.js index b0c02f8a..8a71e94d 100755 --- a/packages/server/src/lib/index.js +++ b/packages/server/src/lib/index.js @@ -1,4 +1,3 @@ export { default as Schematized } from "./schematized" -export { default as additionsHandler } from "./additionsHandler" export * as Token from "./token" \ No newline at end of file diff --git a/packages/server/src/lib/secureEntry/index.js b/packages/server/src/lib/secureEntry/index.js new file mode 100644 index 00000000..e7591da0 --- /dev/null +++ b/packages/server/src/lib/secureEntry/index.js @@ -0,0 +1,133 @@ +import crypto from "crypto" + +export default class SecureEntry { + constructor(model, params = {}) { + this.params = params + + if (!model) { + throw new Error("Missing model") + } + + this.model = model + } + + static get encrytionAlgorithm() { + return "aes-256-cbc" + } + + async set(key, value, { + keyName = "key", + valueName = "value", + }) { + if (!keyName) { + throw new Error("Missing keyName") + } + + if (!valueName) { + throw new Error("Missing valueName") + } + + if (!key) { + throw new Error("Missing key") + } + + if (!value) { + throw new Error("Missing value") + } + + let entry = await this.model.findOne({ + [keyName]: key, + [valueName]: value, + }).catch(() => null) + + const encryptionKey = Buffer.from(process.env.SYNC_ENCRIPT_SECRET, "hex") + const iv = crypto.randomBytes(16) + + const cipher = crypto.createCipheriv(SecureEntry.encrytionAlgorithm, encryptionKey, iv) + + let encryptedData + + try { + encryptedData = cipher.update(value) + } + catch (error) { + console.error(error) + } + + encryptedData = Buffer.concat([encryptedData, cipher.final()]) + + value = iv.toString("hex") + ":" + encryptedData.toString("hex") + + if (entry) { + entry[valueName] = value + + await entry.save() + + return entry + } + + entry = new this.model({ + [keyName]: key, + [valueName]: value, + }) + + await entry.save() + + return entry + } + + async get(key, value, { + keyName = "key", + valueName = "value", + }) { + if (!keyName) { + throw new Error("Missing keyName") + } + if (!key) { + throw new Error("Missing key") + } + + const searchQuery = { + [keyName]: key, + } + + if (value) { + searchQuery[valueName] = value + } + + const entry = await this.model.findOne(searchQuery).catch(() => null) + + if (!entry || !entry[valueName]) { + return null + } + + const encryptionKey = Buffer.from(process.env.SYNC_ENCRIPT_SECRET, "hex") + + const iv = Buffer.from(entry[valueName].split(":")[0], "hex") + const encryptedText = Buffer.from(entry[valueName].split(":")[1], "hex") + + const decipher = crypto.createDecipheriv(SecureEntry.encrytionAlgorithm, encryptionKey, iv) + + let decrypted = decipher.update(encryptedText) + + decrypted = Buffer.concat([decrypted, decipher.final()]) + + return decrypted.toString() + } + + async deleteByID(_id) { + if (!_id) { + throw new Error("Missing _id") + } + + const entry = await this.model.findById(_id).catch(() => null) + + if (!entry) { + return null + } + + await entry.delete() + + return entry + } +} \ No newline at end of file diff --git a/packages/server/src/middlewares/errorHandler/index.js b/packages/server/src/middlewares/errorHandler/index.js deleted file mode 100755 index d8e53df2..00000000 --- a/packages/server/src/middlewares/errorHandler/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export const errorHandler = (error, req, res, next) => { - res.json({ error: error.message }) -} - -export default errorHandler \ No newline at end of file diff --git a/packages/server/src/middlewares/hasPermissions/index.js b/packages/server/src/middlewares/hasPermissions/index.js deleted file mode 100755 index 2cc254a8..00000000 --- a/packages/server/src/middlewares/hasPermissions/index.js +++ /dev/null @@ -1,30 +0,0 @@ -export const hasPermissions = (req, res, next) => { - if (typeof (req.userData) == "undefined") { - return res.status(403).json(`User data is not available, please ensure if you are authenticated`) - } - - const { _id, username, roles } = req.userData - const { permissions } = req.body - - req.userPermissions = roles - - let check = [] - - if (Array.isArray(permissions)) { - check = permissions - } else { - check.push(permissions) - } - - if (check.length > 0) { - check.forEach((role) => { - if (!roles.includes(role)) { - return res.status(403).json(`${username} not have permissions ${permissions}`) - } - }) - } - - next() -} - -export default hasPermissions diff --git a/packages/server/src/middlewares/index.js b/packages/server/src/middlewares/index.js index d22af7db..28f1685b 100755 --- a/packages/server/src/middlewares/index.js +++ b/packages/server/src/middlewares/index.js @@ -1,12 +1,6 @@ -// const fileUpload = require("@nanoexpress/middleware-file-upload/cjs")() - export { default as withAuthentication } from "./withAuthentication" export { default as withOptionalAuthentication } from "./withOptionalAuthentication" -export { default as errorHandler } from "./errorHandler" -export { default as hasPermissions } from "./hasPermissions" export { default as roles } from "./roles" export { default as onlyAdmin } from "./onlyAdmin" -export { default as permissions } from "./permissions" - -// export { fileUpload as fileUpload } \ No newline at end of file +export { default as permissions } from "./permissions" \ No newline at end of file diff --git a/packages/server/src/middlewares/withAuthentication/index.js b/packages/server/src/middlewares/withAuthentication/index.js index b3dcf481..147dd1fe 100755 --- a/packages/server/src/middlewares/withAuthentication/index.js +++ b/packages/server/src/middlewares/withAuthentication/index.js @@ -1,83 +1,119 @@ -import { Session, User } from "../../models" -import { Token } from "../../lib" +import { Session, User, authorizedServerTokens } from "@models" +import { Token } from "@lib" + +import SecureEntry from "@lib/secureEntry" + import jwt from "jsonwebtoken" -export default (req, res, next) => { +export default async (req, res, next) => { function reject(description) { return res.status(403).json({ error: `${description ?? "Invalid session"}` }) } - const authHeader = req.headers?.authorization?.split(" ") + try { + const tokenAuthHeader = req.headers?.authorization?.split(" ") + const serverTokenHeader = req.headers?.server_token - if (authHeader && authHeader[0] === "Bearer") { - const token = authHeader[1] - let decoded = null - - try { - decoded = jwt.decode(token) - } catch (error) { - console.error(error) + if (!serverTokenHeader && !tokenAuthHeader) { + return reject("Missing token header") } - if (!decoded) { - return reject("Cannot decode token") + if (serverTokenHeader) { + const [client_id, token] = serverTokenHeader.split(":") + + if (client_id === "undefined" || token === "undefined") { + return reject("Invalid server token") + } + + const secureEntries = new SecureEntry(authorizedServerTokens) + + const serverTokenEntry = await secureEntries.get(client_id, undefined, { + keyName: "client_id", + valueName: "token", + }) + + if (!serverTokenEntry) { + return reject("Invalid server token") + } + + if (serverTokenEntry !== token) { + return reject("Missmatching server token") + } + + return next() } - jwt.verify(token, global.jwtStrategy.secretOrKey, async (err) => { - const sessions = await Session.find({ user_id: decoded.user_id }) - const currentSession = sessions.find((session) => session.token === token) + if (!serverTokenHeader && tokenAuthHeader && tokenAuthHeader[0] === "Bearer") { + const token = tokenAuthHeader[1] + let decoded = null - if (!currentSession) { - return reject("Cannot find session") + try { + decoded = jwt.decode(token) + } catch (error) { + console.error(error) } - const userData = await User.findOne({ _id: currentSession.user_id }).select("+refreshToken") - - if (!userData) { - return res.status(404).json({ error: "No user data found" }) + if (!decoded) { + return reject("Cannot decode token") } - // if cannot verify token, start regeneration process - if (err) { - // first check if token is only expired, if is corrupted, reject - if (err.name !== "TokenExpiredError") { - return reject("Invalid token, cannot regenerate") + jwt.verify(token, global.jwtStrategy.secretOrKey, async (err) => { + const sessions = await Session.find({ user_id: decoded.user_id }) + const currentSession = sessions.find((session) => session.token === token) + + if (!currentSession) { + return reject("Cannot find session") } - let regenerationToken = null + const userData = await User.findOne({ _id: currentSession.user_id }).select("+refreshToken") - // check if this expired token has a regeneration token associated - const associatedRegenerationToken = await Token.getRegenerationToken(token) + if (!userData) { + return res.status(404).json({ error: "No user data found" }) + } - if (associatedRegenerationToken) { - regenerationToken = associatedRegenerationToken.refreshToken - } else { - // create a new regeneration token with the expired token - regenerationToken = await Token.createNewRegenerationToken(token).catch((error) => { - // in case of error, reject - reject(error.message) + // if cannot verify token, start regeneration process + if (err) { + // first check if token is only expired, if is corrupted, reject + if (err.name !== "TokenExpiredError") { + return reject("Invalid token, cannot regenerate") + } - return null + let regenerationToken = null + + // check if this expired token has a regeneration token associated + const associatedRegenerationToken = await Token.getRegenerationToken(token) + + if (associatedRegenerationToken) { + regenerationToken = associatedRegenerationToken.refreshToken + } else { + // create a new regeneration token with the expired token + regenerationToken = await Token.createNewRegenerationToken(token).catch((error) => { + // in case of error, reject + reject(error.message) + + return null + }) + } + + if (!regenerationToken) return + + // now send the regeneration token to the client (start Expired Exception Event [EEE]) + return res.status(401).json({ + error: "Token expired", + refreshToken: regenerationToken.refreshToken, }) } - if (!regenerationToken) return + req.user = userData + req.jwtToken = token + req.decodedToken = decoded + req.currentSession = currentSession - // now send the regeneration token to the client (start Expired Exception Event [EEE]) - return res.status(401).json({ - error: "Token expired", - refreshToken: regenerationToken.refreshToken, - }) - } - - req.user = userData - req.jwtToken = token - req.decodedToken = decoded - req.currentSession = currentSession - - return next() - }) - } else { - return reject("Missing token header") + return next() + }) + } + } catch (error) { + console.error(error) + return res.status(500).json({ error: "This endpoint needs authentication, but an error occurred." }) } } diff --git a/packages/server/src/models/authorizedServerTokens/index.js b/packages/server/src/models/authorizedServerTokens/index.js new file mode 100644 index 00000000..b569fc49 --- /dev/null +++ b/packages/server/src/models/authorizedServerTokens/index.js @@ -0,0 +1,28 @@ +export default { + name: "authorizedServerTokens", + collection: "authorizedServerTokens", + schema: { + client_id: { + type: String, + required: true, + }, + token: { + type: String, + required: true, + }, + access: { + type: Array, + default: [], + }, + name: { + type: String, + }, + description: { + type: String, + }, + createdAt: { + type: Date, + default: Date.now, + }, + } +} \ No newline at end of file diff --git a/packages/server/src/setup/authorizeSelfServerToken/index.js b/packages/server/src/setup/authorizeSelfServerToken/index.js new file mode 100644 index 00000000..243dbf8b --- /dev/null +++ b/packages/server/src/setup/authorizeSelfServerToken/index.js @@ -0,0 +1,29 @@ +import SecureEntry from "@lib/secureEntry" +import { authorizedServerTokens } from "@models" + +const rootClientID = "00000000-0000-0000-000000000000" + +export default async () => { + // check if process.env.SERVER_TOKEN is included in authorizedServerKeys + if (process.env.SERVER_TOKEN) { + console.log("Checking if server token is authorized on server tokens list...") + + const secureEntries = new SecureEntry(authorizedServerTokens) + + const currentServerToken = await secureEntries.get(rootClientID, undefined, { + keyName: "client_id", + }) + + // check if match or not exist, if not, update + if (currentServerToken !== process.env.SERVER_TOKEN) { + console.log("Server token is not authorized on server tokens list, updating...") + + await secureEntries.set(rootClientID, process.env.SERVER_TOKEN, { + keyName: "client_id", + valueName: "token", + }) + } + + return true + } +} \ No newline at end of file diff --git a/packages/server/src/setup/dbAdmin/index.js b/packages/server/src/setup/dbAdmin/index.js index 884e6efa..61c99002 100755 --- a/packages/server/src/setup/dbAdmin/index.js +++ b/packages/server/src/setup/dbAdmin/index.js @@ -1,5 +1,5 @@ -import { User } from "../../models" -import createUser from "../../controllers/UserController/methods/createUser" +import { User } from "@models" +import createUser from "@controllers/UserController/services/createUser" export default async () => { // check if any user with includes admin role exists diff --git a/packages/server/src/setup/index.js b/packages/server/src/setup/index.js index e136e2f9..6692cffd 100755 --- a/packages/server/src/setup/index.js +++ b/packages/server/src/setup/index.js @@ -1,6 +1,8 @@ import { default as dbAdmin } from "./dbAdmin" +import { default as authorizeSelfServerToken } from "./authorizeSelfServerToken" // set here the setup functions export default [ dbAdmin, + authorizeSelfServerToken, ] \ No newline at end of file diff --git a/packages/server/src/utils/fullfillPostsData/index.js b/packages/server/src/utils/fullfillPostsData/index.js index 17ec1531..12caeba6 100755 --- a/packages/server/src/utils/fullfillPostsData/index.js +++ b/packages/server/src/utils/fullfillPostsData/index.js @@ -1,4 +1,4 @@ -import { User, Comment, SavedPost } from "../../models" +import { User, Comment, SavedPost } from "@models" export default async (payload) => { let {