From ca174fec9d7199d103b029cc54234e3082f2a1b9 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Mon, 12 May 2025 17:20:16 -0600 Subject: [PATCH 01/10] allow hiding followers, add get following --- api/v1/db/UserManager.js | 16 +++++ .../users/meta/following/getFollowers.js | 46 ++++++++++++-- .../users/meta/following/getFollowing.js | 62 +++++++++++++++++++ .../users/meta/privateFollowSettings.js | 28 +++++++++ 4 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 api/v1/routes/users/meta/following/getFollowing.js create mode 100644 api/v1/routes/users/meta/privateFollowSettings.js diff --git a/api/v1/db/UserManager.js b/api/v1/db/UserManager.js index 02ff1202..e1981928 100644 --- a/api/v1/db/UserManager.js +++ b/api/v1/db/UserManager.js @@ -3861,6 +3861,22 @@ class UserManager { await this.users.updateOne({ username: username }, { $set: { allowFollowingView: toggle } }); } + async setProfileHideFollowing(username, toggle) { + await this.users.updateOne({ username: username }, { $set: { profileHideFollowing: toggle } }); + } + async setProfileHideFollowers(username, toggle) { + await this.users.updateOne({ username: username }, { $set: { profileHideFollowers: toggle } }); + } + + async getProfileHideFollowing(username) { + const result = await this.users.findOne({ username: username }); + return result.profileHideFollowing; + } + async getProfileHideFollowers(username) { + const result = await this.users.findOne({ username: username }); + return result.profileHideFollowers; + } + /** * Temporarily ban a user * @param {string} username Username of the user diff --git a/api/v1/routes/users/meta/following/getFollowers.js b/api/v1/routes/users/meta/following/getFollowers.js index ca69b624..64eb643b 100644 --- a/api/v1/routes/users/meta/following/getFollowers.js +++ b/api/v1/routes/users/meta/following/getFollowers.js @@ -2,19 +2,57 @@ module.exports = (app, utils) => { app.get("/api/v1/users/meta/getfollowers", async function (req, res) { const packet = req.query; - const username = (String(packet.username)).toLowerCase(); + // meant for getting the data + const target = (String(packet.target)).toLowerCase(); const page = utils.handle_page(packet.page); - if (!username) { + if (!target) { utils.error(res, 400, "Missing username"); return; } - - if (!await utils.UserManager.existsByUsername(username)) { + if (!await utils.UserManager.existsByUsername(target)) { utils.error(res, 404, "User not found"); return; } + // incase the user hides followers, check if we are the user/a mod + const username = String(packet.username).toLowerCase(); + const token = packet.token || ""; + + let loggedIn = await utils.UserManager.loginWithToken(username, token); + + const target_data = await utils.UserManager.getUserData(target); + const user_data = await utils.UserManager.getUserData(username); + const isMod = loggedIn ? (user_data.moderator || user_data.admin) : false; + + // if not logged in, or we arent a mod and the current acc is not the target + if (!loggedIn || (!isMod && (username !== target))) { + if (target_data.privateProfile) { + // if its a private profile, error if we arent logged in, the account doesnt let following view their profile, or we arent being followed by them + if (!loggedIn || !target_data.allowFollowingView) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + + const usernameID = await utils.UserManager.getIDByUsername(username); + const isFollowing = await utils.UserManager.isFollowing(usernameID, target_data.id); + if (!isFollowing) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + } + if (utils.UserManager.getProfileHideFollowers(target)) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "Hidden" }); + return; + } + } + const followers = await utils.UserManager.getFollowers(username, page, Number(utils.env.PageSize)); res.status(200); diff --git a/api/v1/routes/users/meta/following/getFollowing.js b/api/v1/routes/users/meta/following/getFollowing.js new file mode 100644 index 00000000..b9dd5087 --- /dev/null +++ b/api/v1/routes/users/meta/following/getFollowing.js @@ -0,0 +1,62 @@ +module.exports = (app, utils) => { + app.get("/api/v1/users/meta/getfollowing", async function (req, res) { + const packet = req.query; + + // meant for getting the data + const target = (String(packet.target)).toLowerCase(); + const page = utils.handle_page(packet.page); + + if (!target) { + utils.error(res, 400, "Missing username"); + return; + } + if (!await utils.UserManager.existsByUsername(target)) { + utils.error(res, 404, "User not found"); + return; + } + + // incase the user hides followers, check if we are the user/a mod + const username = String(packet.username).toLowerCase(); + const token = packet.token || ""; + + let loggedIn = await utils.UserManager.loginWithToken(username, token); + + const target_data = await utils.UserManager.getUserData(target); + const user_data = await utils.UserManager.getUserData(username); + const isMod = loggedIn ? (user_data.moderator || user_data.admin) : false; + + // if not logged in, or we arent a mod and the current acc is not the target + if (!loggedIn || (!isMod && (username !== target))) { + if (target_data.privateProfile) { + // if its a private profile, error if we arent logged in, the account doesnt let following view their profile, or we arent being followed by them + if (!loggedIn || !target_data.allowFollowingView) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + + const usernameID = await utils.UserManager.getIDByUsername(username); + const isFollowing = await utils.UserManager.isFollowing(usernameID, target_data.id); + if (!isFollowing) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + } + if (utils.UserManager.getProfileHideFollowing(target)) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "Hidden" }); + return; + } + } + + const following = await utils.UserManager.getFollowing(username, page, Number(utils.env.PageSize)); + + res.status(200); + res.header("Content-Type", 'application/json'); + res.send(following); + }); +} \ No newline at end of file diff --git a/api/v1/routes/users/meta/privateFollowSettings.js b/api/v1/routes/users/meta/privateFollowSettings.js new file mode 100644 index 00000000..ebe996de --- /dev/null +++ b/api/v1/routes/users/meta/privateFollowSettings.js @@ -0,0 +1,28 @@ +module.exports = (app, utils) => { + app.post('/api/v1/users/privateFollowSettings', utils.cors(), async function (req, res) { + const packet = req.body; + + const username = String(packet.username).toLowerCase(); + const token = packet.token; + + if (!await utils.UserManager.loginWithToken(username, token)) { + utils.error(res, 401, "Reauthenticate"); + return; + } + + const profileHideFollowing = packet.profileHideFollowing; + const profileHideFollowers = packet.profileHideFollowers; + + if (typeof profileHideFollowing !== "boolean" || typeof profileHideFollowers !== "boolean") { + utils.error(res, 400, "InvalidBody") + return; + } + + await utils.UserManager.setProfileHideFollowing(username, profileHideFollowing); + await utils.UserManager.setProfileHideFollowers(username, profileHideFollowers); + + res.status(200); + res.header("Content-Type", "application/json"); + res.send({ success: true }); + }); +} \ No newline at end of file From c7d3e455f4a3117f9d5f0ba3c59b7fdccac09e23 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Mon, 12 May 2025 18:05:03 -0600 Subject: [PATCH 02/10] false by default --- api/v1/db/UserManager.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/v1/db/UserManager.js b/api/v1/db/UserManager.js index e1981928..dc3e0656 100644 --- a/api/v1/db/UserManager.js +++ b/api/v1/db/UserManager.js @@ -275,6 +275,8 @@ class UserManager { lastGuidelinesRead: current_time, privateProfile: false, allowFollowingView: false, + profileHideFollowing: false, + profileHideFollowers: false, is_studio, }); @@ -3870,11 +3872,11 @@ class UserManager { async getProfileHideFollowing(username) { const result = await this.users.findOne({ username: username }); - return result.profileHideFollowing; + return result.profileHideFollowing || false; } async getProfileHideFollowers(username) { const result = await this.users.findOne({ username: username }); - return result.profileHideFollowers; + return result.profileHideFollowers || false; } /** From 1a62aecfe41473f816e745e9a2d441ed484fe993 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Mon, 12 May 2025 18:54:44 -0600 Subject: [PATCH 03/10] make profile check less confusing & fix priv check --- api/v1/routes/users/meta/following/getFollowers.js | 2 +- api/v1/routes/users/meta/following/getFollowing.js | 2 +- api/v1/routes/users/meta/following/isFollowing.js | 2 ++ api/v1/routes/users/profile.js | 5 +++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api/v1/routes/users/meta/following/getFollowers.js b/api/v1/routes/users/meta/following/getFollowers.js index 64eb643b..ee27150f 100644 --- a/api/v1/routes/users/meta/following/getFollowers.js +++ b/api/v1/routes/users/meta/following/getFollowers.js @@ -37,7 +37,7 @@ module.exports = (app, utils) => { } const usernameID = await utils.UserManager.getIDByUsername(username); - const isFollowing = await utils.UserManager.isFollowing(usernameID, target_data.id); + const isFollowing = await utils.UserManager.isFollowing(target_data.id, usernameID); if (!isFollowing) { res.status(403); res.header("Content-Type", "application/json"); diff --git a/api/v1/routes/users/meta/following/getFollowing.js b/api/v1/routes/users/meta/following/getFollowing.js index b9dd5087..25bc1339 100644 --- a/api/v1/routes/users/meta/following/getFollowing.js +++ b/api/v1/routes/users/meta/following/getFollowing.js @@ -37,7 +37,7 @@ module.exports = (app, utils) => { } const usernameID = await utils.UserManager.getIDByUsername(username); - const isFollowing = await utils.UserManager.isFollowing(usernameID, target_data.id); + const isFollowing = await utils.UserManager.isFollowing(target_data.id, usernameID); if (!isFollowing) { res.status(403); res.header("Content-Type", "application/json"); diff --git a/api/v1/routes/users/meta/following/isFollowing.js b/api/v1/routes/users/meta/following/isFollowing.js index ff515467..a3f1598e 100644 --- a/api/v1/routes/users/meta/following/isFollowing.js +++ b/api/v1/routes/users/meta/following/isFollowing.js @@ -20,6 +20,8 @@ module.exports = (app, utils) => { return; } + // TODO: Block following check the same way as getFollowing + const usernameID = await utils.UserManager.getIDByUsername(username); const targetID = await utils.UserManager.getIDByUsername(target); diff --git a/api/v1/routes/users/profile.js b/api/v1/routes/users/profile.js index 05675c71..02739809 100644 --- a/api/v1/routes/users/profile.js +++ b/api/v1/routes/users/profile.js @@ -63,9 +63,10 @@ module.exports = (app, utils) => { if (username !== target) { const usernameID = await utils.UserManager.getIDByUsername(username); - const isFollowing = await utils.UserManager.isFollowing(usernameID, targetID); + const isTargetFollowingUser = await utils.UserManager.isFollowing(targetID, usernameID); - if (!isFollowing && !canFollowingSeeProfile && !isMod) { + // if we arent a mod, then error if followers cant see the profile or if they can but you arent a follower + if (!isMod && (!canFollowingSeeProfile || (canFollowingSeeProfile && !isTargetFollowingUser))) { res.status(200); res.header("Content-Type", "application/json"); res.send(user); From 912ac86947b68a689e09b1180b26aa78d533a3dd Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Mon, 12 May 2025 19:00:21 -0600 Subject: [PATCH 04/10] lebron reportedly forgot to await his promises --- api/v1/routes/users/meta/following/getFollowers.js | 4 ++-- api/v1/routes/users/meta/following/getFollowing.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v1/routes/users/meta/following/getFollowers.js b/api/v1/routes/users/meta/following/getFollowers.js index ee27150f..dfd3f03d 100644 --- a/api/v1/routes/users/meta/following/getFollowers.js +++ b/api/v1/routes/users/meta/following/getFollowers.js @@ -45,7 +45,7 @@ module.exports = (app, utils) => { return; } } - if (utils.UserManager.getProfileHideFollowers(target)) { + if (await utils.UserManager.getProfileHideFollowing(target)) { res.status(403); res.header("Content-Type", "application/json"); res.json({ "error": "Hidden" }); @@ -53,7 +53,7 @@ module.exports = (app, utils) => { } } - const followers = await utils.UserManager.getFollowers(username, page, Number(utils.env.PageSize)); + const followers = await utils.UserManager.getFollowers(target, page, Number(utils.env.PageSize)); res.status(200); res.header("Content-Type", 'application/json'); diff --git a/api/v1/routes/users/meta/following/getFollowing.js b/api/v1/routes/users/meta/following/getFollowing.js index 25bc1339..2cdbeab8 100644 --- a/api/v1/routes/users/meta/following/getFollowing.js +++ b/api/v1/routes/users/meta/following/getFollowing.js @@ -45,7 +45,7 @@ module.exports = (app, utils) => { return; } } - if (utils.UserManager.getProfileHideFollowing(target)) { + if (await utils.UserManager.getProfileHideFollowing(target)) { res.status(403); res.header("Content-Type", "application/json"); res.json({ "error": "Hidden" }); @@ -53,7 +53,7 @@ module.exports = (app, utils) => { } } - const following = await utils.UserManager.getFollowing(username, page, Number(utils.env.PageSize)); + const following = await utils.UserManager.getFollowing(target, page, Number(utils.env.PageSize)); res.status(200); res.header("Content-Type", 'application/json'); From 45308e5b8881dd78d7a1254912152126fb155b62 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Mon, 12 May 2025 20:01:35 -0600 Subject: [PATCH 05/10] perhaps this will hide following hiddens --- api/v1/db/UserManager.js | 3 ++- api/v1/routes/users/meta/privateFollowSettings.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/v1/db/UserManager.js b/api/v1/db/UserManager.js index dc3e0656..213aced0 100644 --- a/api/v1/db/UserManager.js +++ b/api/v1/db/UserManager.js @@ -1993,7 +1993,8 @@ class UserManager { }, { $match: { - "follower.banned": false + "follower.banned": false, + "follower.profileHideFollowing": { $ne: true } } }, { diff --git a/api/v1/routes/users/meta/privateFollowSettings.js b/api/v1/routes/users/meta/privateFollowSettings.js index ebe996de..2e4037ca 100644 --- a/api/v1/routes/users/meta/privateFollowSettings.js +++ b/api/v1/routes/users/meta/privateFollowSettings.js @@ -11,7 +11,7 @@ module.exports = (app, utils) => { } const profileHideFollowing = packet.profileHideFollowing; - const profileHideFollowers = packet.profileHideFollowers; + const profileHideFollowers = false; // NOTE: Actually, hiding your follower list doesnt really make sense... if (typeof profileHideFollowing !== "boolean" || typeof profileHideFollowers !== "boolean") { utils.error(res, 400, "InvalidBody") From a80b7a8debef623b18ccbce5caefc811ee9a8e67 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Fri, 18 Jul 2025 13:34:41 -0600 Subject: [PATCH 06/10] work with new loginWithToken --- api/v1/routes/users/meta/following/getFollowers.js | 3 ++- api/v1/routes/users/meta/following/getFollowing.js | 3 ++- api/v1/routes/users/meta/privateFollowSettings.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/api/v1/routes/users/meta/following/getFollowers.js b/api/v1/routes/users/meta/following/getFollowers.js index 69b7beb1..5ce9f4a1 100644 --- a/api/v1/routes/users/meta/following/getFollowers.js +++ b/api/v1/routes/users/meta/following/getFollowers.js @@ -31,7 +31,8 @@ module.exports = (app, utils) => { const username = String(packet.username).toLowerCase(); const token = packet.token || ""; - let loggedIn = await utils.UserManager.loginWithToken(username, token); + const login = await utils.UserManager.loginWithToken(username, token); + let loggedIn = login.success; const target_data = await utils.UserManager.getUserData(target); const user_data = await utils.UserManager.getUserData(username); diff --git a/api/v1/routes/users/meta/following/getFollowing.js b/api/v1/routes/users/meta/following/getFollowing.js index 2cdbeab8..90607a32 100644 --- a/api/v1/routes/users/meta/following/getFollowing.js +++ b/api/v1/routes/users/meta/following/getFollowing.js @@ -19,7 +19,8 @@ module.exports = (app, utils) => { const username = String(packet.username).toLowerCase(); const token = packet.token || ""; - let loggedIn = await utils.UserManager.loginWithToken(username, token); + const login = await utils.UserManager.loginWithToken(username, token); + let loggedIn = login.success; const target_data = await utils.UserManager.getUserData(target); const user_data = await utils.UserManager.getUserData(username); diff --git a/api/v1/routes/users/meta/privateFollowSettings.js b/api/v1/routes/users/meta/privateFollowSettings.js index 2e4037ca..ac74dfd5 100644 --- a/api/v1/routes/users/meta/privateFollowSettings.js +++ b/api/v1/routes/users/meta/privateFollowSettings.js @@ -5,7 +5,8 @@ module.exports = (app, utils) => { const username = String(packet.username).toLowerCase(); const token = packet.token; - if (!await utils.UserManager.loginWithToken(username, token)) { + const login = await utils.UserManager.loginWithToken(token); + if (!login.success) { utils.error(res, 401, "Reauthenticate"); return; } From 0535961e8bf2b4896bac412aa34bcff462260779 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Sat, 26 Jul 2025 16:28:15 -0600 Subject: [PATCH 07/10] getFollowingCount and following count on profiles --- api/v1/db/UserManager.js | 13 ++++++++++++- api/v1/routes/users/profile.js | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/api/v1/db/UserManager.js b/api/v1/db/UserManager.js index 1817b8c6..133d93ec 100644 --- a/api/v1/db/UserManager.js +++ b/api/v1/db/UserManager.js @@ -2150,10 +2150,21 @@ class UserManager { */ async getFollowerCount(username) { const result = await this.users.findOne({username: username}); - + return result.followers; } + /** + * Get the amount of people a user is following + * @param {string} username Username of the user + * @returns {Promise} Amount of people the user is following + */ + async getFollowingCount(username) { + const result = await this.users.findOne({ username: username }); + + return result.following; + } + /** * Send a message * @param {string} receiver ID of the person receiving the message diff --git a/api/v1/routes/users/profile.js b/api/v1/routes/users/profile.js index 1d534400..8e0f7ecc 100644 --- a/api/v1/routes/users/profile.js +++ b/api/v1/routes/users/profile.js @@ -41,6 +41,7 @@ module.exports = (app, utils) => { const privateProfile = target_data.privateProfile; const canFollowingSeeProfile = target_data.allowFollowingView; + const canSeeFollowing = !target_data.profileHideFollowing; let user = { success: false, @@ -54,9 +55,11 @@ module.exports = (app, utils) => { myFeaturedProject: "", myFeaturedProjectTitle: "", followers: 0, + following: 0, canrankup: false, privateProfile, canFollowingSeeProfile, + canSeeFollowing, isFollowing: false, }; @@ -102,6 +105,8 @@ module.exports = (app, utils) => { || (badges.length > 0); // or we have a badge const followers = await utils.UserManager.getFollowerCount(target); + const following = await utils.UserManager.getFollowingCount(target); + const canActuallySeeFollowing = canSeeFollowing || (!canSeeFollowing && ((loggedIn && username === target) || isMod)) const myFeaturedProject = await utils.UserManager.getFeaturedProject(target); const myFeaturedProjectTitle = await utils.UserManager.getFeaturedProjectTitle(target); @@ -120,9 +125,11 @@ module.exports = (app, utils) => { myFeaturedProject, myFeaturedProjectTitle, followers: followers, + following: canActuallySeeFollowing ? following : 0, canrankup: canRequestRankUp && rank !== 1, privateProfile, canFollowingSeeProfile, + canSeeFollowing, isFollowing: user.isFollowing, }; From d55db7796d326b58f7ea6103c42aaebd599bf080 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Sat, 26 Jul 2025 17:30:17 -0600 Subject: [PATCH 08/10] actually work with loginWithToken this time --- .../routes/users/meta/following/getFollowers.js | 10 ++-------- .../routes/users/meta/following/getFollowing.js | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/api/v1/routes/users/meta/following/getFollowers.js b/api/v1/routes/users/meta/following/getFollowers.js index 5ce9f4a1..4deba7d6 100644 --- a/api/v1/routes/users/meta/following/getFollowers.js +++ b/api/v1/routes/users/meta/following/getFollowers.js @@ -28,10 +28,10 @@ module.exports = (app, utils) => { } // incase the user hides followers, check if we are the user/a mod - const username = String(packet.username).toLowerCase(); const token = packet.token || ""; - const login = await utils.UserManager.loginWithToken(username, token); + const login = await utils.UserManager.loginWithToken(token); + let username = login.username; let loggedIn = login.success; const target_data = await utils.UserManager.getUserData(target); @@ -58,12 +58,6 @@ module.exports = (app, utils) => { return; } } - if (await utils.UserManager.getProfileHideFollowing(target)) { - res.status(403); - res.header("Content-Type", "application/json"); - res.json({ "error": "Hidden" }); - return; - } } const followers = await utils.UserManager.getFollowers(target, page, Number(utils.env.PageSize)); diff --git a/api/v1/routes/users/meta/following/getFollowing.js b/api/v1/routes/users/meta/following/getFollowing.js index 90607a32..d542f80c 100644 --- a/api/v1/routes/users/meta/following/getFollowing.js +++ b/api/v1/routes/users/meta/following/getFollowing.js @@ -1,3 +1,15 @@ +const UserManager = require("../../../../db/UserManager"); + +/** + * @typedef {Object} Utils + * @property {UserManager} UserManager + */ + +/** + * + * @param {any} app Express app + * @param {Utils} utils Utils + */ module.exports = (app, utils) => { app.get("/api/v1/users/meta/getfollowing", async function (req, res) { const packet = req.query; @@ -16,10 +28,10 @@ module.exports = (app, utils) => { } // incase the user hides followers, check if we are the user/a mod - const username = String(packet.username).toLowerCase(); const token = packet.token || ""; - const login = await utils.UserManager.loginWithToken(username, token); + const login = await utils.UserManager.loginWithToken(token); + let username = login.username; let loggedIn = login.success; const target_data = await utils.UserManager.getUserData(target); From 51ce4873b0c30e74bee6e71acf2c55f9fa8fb5a4 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Sat, 26 Jul 2025 18:06:22 -0600 Subject: [PATCH 09/10] block isFollowing if user hides following --- .../users/meta/following/getFollowers.js | 6 ++ .../users/meta/following/getFollowing.js | 2 +- .../users/meta/following/isFollowing.js | 72 ++++++++++++++++++- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/api/v1/routes/users/meta/following/getFollowers.js b/api/v1/routes/users/meta/following/getFollowers.js index 4deba7d6..12d0cf23 100644 --- a/api/v1/routes/users/meta/following/getFollowers.js +++ b/api/v1/routes/users/meta/following/getFollowers.js @@ -58,6 +58,12 @@ module.exports = (app, utils) => { return; } } + if (await utils.UserManager.getProfileHideFollowers(target)) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "Hidden" }); + return; + } } const followers = await utils.UserManager.getFollowers(target, page, Number(utils.env.PageSize)); diff --git a/api/v1/routes/users/meta/following/getFollowing.js b/api/v1/routes/users/meta/following/getFollowing.js index d542f80c..f75d7875 100644 --- a/api/v1/routes/users/meta/following/getFollowing.js +++ b/api/v1/routes/users/meta/following/getFollowing.js @@ -27,7 +27,7 @@ module.exports = (app, utils) => { return; } - // incase the user hides followers, check if we are the user/a mod + // incase the user hides following, check if we are the user/a mod const token = packet.token || ""; const login = await utils.UserManager.loginWithToken(token); diff --git a/api/v1/routes/users/meta/following/isFollowing.js b/api/v1/routes/users/meta/following/isFollowing.js index 080e48e9..81fa52a2 100644 --- a/api/v1/routes/users/meta/following/isFollowing.js +++ b/api/v1/routes/users/meta/following/isFollowing.js @@ -17,6 +17,7 @@ module.exports = (app, utils) => { const username = (String(packet.username)).toLowerCase(); const target = (String(packet.target)).toLowerCase(); + // check that these accs exist if (!username || !target) { utils.error(res, 400, "Missing username or target"); return; @@ -26,19 +27,84 @@ module.exports = (app, utils) => { utils.error(res, 404, "NotFound"); return; } - if (!await utils.UserManager.existsByUsername(target)) { utils.error(res, 404, "NotFound"); return; } - // TODO: Block following check the same way as getFollowing + // incase the users have some privacy setting, check if we are a mod + const token = packet.token || ""; + const login = await utils.UserManager.loginWithToken(token); + let fetcherUsername = login.username; + let loggedIn = login.success; + + // get all of the data for this req + const target_data = await utils.UserManager.getUserData(target); + const user_data = await utils.UserManager.getUserData(username); + const fetcher_data = await utils.UserManager.getUserData(fetcherUsername); + const fetcherIsMod = loggedIn ? (fetcher_data.moderator || fetcher_data.admin) : false; const usernameID = await utils.UserManager.getIDByUsername(username); const targetID = await utils.UserManager.getIDByUsername(target); + const fetcherID = await utils.UserManager.getIDByUsername(fetcherUsername); - const isFollowing = await utils.UserManager.isFollowing(usernameID, targetID); + // if not logged in, or we arent a mod + if (!loggedIn || !fetcherIsMod) { + // this is a bit complicated: + // we need to see if the user has a private profile/if we can see that profile. if we can, we need to be able to see who they are following. + // we need to see if the target has a private profile/if we can see that profile. if we can, we need to be able to see their followers. + // see if user is private + if (user_data.privateProfile) { + if (!loggedIn || !user_data.allowFollowingView) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + // people the user follows can see the user's profile + const isFollowing = await utils.UserManager.isFollowing(usernameID, fetcherID); + if (!isFollowing) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + } + // see if user hides their following + if (await utils.UserManager.getProfileHideFollowing(username)) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "Hidden" }); + return; + } + // see if target is private + if (target_data.privateProfile) { + if (!loggedIn || !target_data.allowFollowingView) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + // people the target follows can see the target's profile + const isFollowing = await utils.UserManager.isFollowing(targetID, fetcherID); + if (!isFollowing) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "PrivateProfile" }); + return; + } + } + // see if target hides their followers + if (await utils.UserManager.getProfileHideFollowers(target)) { + res.status(403); + res.header("Content-Type", "application/json"); + res.json({ "error": "Hidden" }); + return; + } + } + // user doesnt hide who they follow, and target doesnt hide their followers + const isFollowing = await utils.UserManager.isFollowing(usernameID, targetID); res.status(200); res.header("Content-Type", 'application/json'); res.send({ following: isFollowing }); From a2d33d8dd1e79195f18361f9e771ee12f0f1f766 Mon Sep 17 00:00:00 2001 From: JeremyGamer13 <69337718+JeremyGamer13@users.noreply.github.com> Date: Sat, 26 Jul 2025 18:21:29 -0600 Subject: [PATCH 10/10] dont crash if not logged in --- api/v1/routes/users/meta/following/isFollowing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1/routes/users/meta/following/isFollowing.js b/api/v1/routes/users/meta/following/isFollowing.js index 81fa52a2..62134759 100644 --- a/api/v1/routes/users/meta/following/isFollowing.js +++ b/api/v1/routes/users/meta/following/isFollowing.js @@ -46,7 +46,7 @@ module.exports = (app, utils) => { const usernameID = await utils.UserManager.getIDByUsername(username); const targetID = await utils.UserManager.getIDByUsername(target); - const fetcherID = await utils.UserManager.getIDByUsername(fetcherUsername); + const fetcherID = loggedIn ? await utils.UserManager.getIDByUsername(fetcherUsername) : null; // if not logged in, or we arent a mod if (!loggedIn || !fetcherIsMod) {