|
| 1 | +const Users = require("../../Database/Models/Users"); |
| 2 | +const Entity = require("../../Database/Models/Entity"); |
| 3 | +const Song = require("../../Database/Models/Song"); |
| 4 | +const utils = require("../../utils"); |
| 5 | +const admin = async (req, res) => { |
| 6 | + const { user, adminAction } = req.body; |
| 7 | + if (!user || user?.role !== "admin") { |
| 8 | + return res.status(403).json({ status: false, msg: "Unauthorized access!" }); |
| 9 | + } |
| 10 | + try { |
| 11 | + if (!adminAction) { |
| 12 | + return res.status(400).json({ status: false, msg: "Invalid input!" }); |
| 13 | + } |
| 14 | + |
| 15 | + if (adminAction?.action === "getCounts") { |
| 16 | + const totalUsers = await Users.aggregate([ |
| 17 | + { |
| 18 | + $facet: { |
| 19 | + approved: [ |
| 20 | + { $match: { downloadAccess: "approved" } }, |
| 21 | + { $count: "count" }, |
| 22 | + ], |
| 23 | + users: [{ $match: { role: "user" } }, { $count: "count" }], |
| 24 | + }, |
| 25 | + }, |
| 26 | + ]); |
| 27 | + |
| 28 | + const detailData = await Users.aggregate([ |
| 29 | + { |
| 30 | + $facet: { |
| 31 | + admins: [ |
| 32 | + { $match: { role: "admin" } }, |
| 33 | + { $project: { username: 1, pic: 1, createdAt: 1 } }, |
| 34 | + ], |
| 35 | + requests: [ |
| 36 | + { $match: { downloadAccess: "requested" } }, |
| 37 | + { $project: { username: 1, pic: 1, createdAt: 1, id: 1 } }, |
| 38 | + ], |
| 39 | + }, |
| 40 | + }, |
| 41 | + ]); |
| 42 | + |
| 43 | + const UsersCount = Object.fromEntries( |
| 44 | + Object.entries(totalUsers[0]).map(([key, value]) => [ |
| 45 | + key, |
| 46 | + value[0]?.count || 0, |
| 47 | + ]) |
| 48 | + ); |
| 49 | + |
| 50 | + UsersCount.admin = detailData[0].admins?.length || 0; |
| 51 | + UsersCount.request = detailData[0].requests?.length || 0; |
| 52 | + |
| 53 | + const totalEntity = await Entity.aggregate([ |
| 54 | + { |
| 55 | + $facet: { |
| 56 | + playlists: [{ $match: { type: "playlist" } }, { $count: "count" }], |
| 57 | + albums: [{ $match: { type: "album" } }, { $count: "count" }], |
| 58 | + mixes: [{ $match: { type: "mix" } }, { $count: "count" }], |
| 59 | + }, |
| 60 | + }, |
| 61 | + ]); |
| 62 | + const EntityCount = Object.fromEntries( |
| 63 | + Object.entries(totalEntity[0]).map(([key, value]) => [ |
| 64 | + key, |
| 65 | + value[0]?.count || 0, |
| 66 | + ]) |
| 67 | + ); |
| 68 | + |
| 69 | + const songCount = await Song.countDocuments({}); |
| 70 | + EntityCount.songs = songCount; |
| 71 | + |
| 72 | + return res.status(200).json({ |
| 73 | + status: true, |
| 74 | + data: { UsersCount, EntityCount, detailData: detailData[0] }, |
| 75 | + }); |
| 76 | + } |
| 77 | + if (adminAction?.action === "searchUser") { |
| 78 | + const { searchId } = adminAction; |
| 79 | + if (!searchId) { |
| 80 | + return res.status(400).json({ status: false, msg: "Invalid input!" }); |
| 81 | + } |
| 82 | + const isValidUsername = utils.isValidUsername(searchId); |
| 83 | + if (!isValidUsername && !utils.isValidEmail(searchId)) { |
| 84 | + return res.status(400).json({ status: false, msg: "Invalid input!" }); |
| 85 | + } |
| 86 | + |
| 87 | + const usersData = await Users.find( |
| 88 | + { |
| 89 | + username: { $regex: new RegExp("^" + searchId), $options: "i" }, |
| 90 | + }, |
| 91 | + ["username", "id", "pic", "role", "createdAt", "downloadAccess", "-_id"] |
| 92 | + ); |
| 93 | + |
| 94 | + return res.status(200).json({ |
| 95 | + status: true, |
| 96 | + data: usersData, |
| 97 | + }); |
| 98 | + } |
| 99 | + |
| 100 | + if (adminAction?.action === "updateRole") { |
| 101 | + const { targetId, role } = adminAction; |
| 102 | + if (!targetId || !role) { |
| 103 | + return res.status(400).json({ status: false, msg: "Invalid input!" }); |
| 104 | + } |
| 105 | + const validRoles = ["user", "admin"]; |
| 106 | + if (!validRoles.includes(role)) { |
| 107 | + return res.status(400).json({ status: false, msg: "Invalid role!" }); |
| 108 | + } |
| 109 | + |
| 110 | + const userData = await Users.findOneAndUpdate( |
| 111 | + { id: targetId }, |
| 112 | + { $set: { role: role } }, |
| 113 | + { new: true } |
| 114 | + ); |
| 115 | + |
| 116 | + if (!userData) { |
| 117 | + return res.status(404).json({ status: false, msg: "User not found!" }); |
| 118 | + } |
| 119 | + sendEmail( |
| 120 | + userData?.username, |
| 121 | + [{ email: userData?.email, name: userData?.username }], |
| 122 | + role |
| 123 | + ); |
| 124 | + |
| 125 | + return res.status(200).json({ |
| 126 | + status: true, |
| 127 | + msg: `User role updated successfully!`, |
| 128 | + }); |
| 129 | + } |
| 130 | + return res |
| 131 | + .status(200) |
| 132 | + .json({ status: false, msg: "Invalid admin action!" }); |
| 133 | + } catch (error) { |
| 134 | + console.log(error); |
| 135 | + return res |
| 136 | + .status(500) |
| 137 | + .json({ status: false, msg: "something went wrong!" }); |
| 138 | + } |
| 139 | +}; |
| 140 | + |
| 141 | +const sendEmail = async (username, emails, type) => { |
| 142 | + if (!username || !emails || !type) return; |
| 143 | + let message = ""; |
| 144 | + let subject = ""; |
| 145 | + |
| 146 | + if (type == "admin") { |
| 147 | + subject = "Welcome to the HTh Beats Admin Team!"; |
| 148 | + |
| 149 | + message = |
| 150 | + `Dear ${username},\n\n` + |
| 151 | + `Congratulations! 🎉 You have been promoted to the Admin Team on HTh Beats.\n\n` + |
| 152 | + `As an admin, you now have access to several new responsibilities and capabilities:\n` + |
| 153 | + `• Approve or deny download requests submitted by users\n` + |
| 154 | + `• Grant or revoke download permissions, even if a request hasn't been made\n` + |
| 155 | + `• Promote other users to admin or remove current admins\n` + |
| 156 | + `• View internal statistics related to HTh Beats' usage and activity\n\n` + |
| 157 | + `To access the Admin Panel, please use the link below:\n` + |
| 158 | + `${process.env.FURL}/admin\n\n` + |
| 159 | + `If the above link doesn’t work for any reason, simply open your account settings within the app and look for the “Admin Panel” button.\n\n` + |
| 160 | + `We trust that you will use your new role responsibly and help maintain the quality and fairness of our platform. If for any reason you do not wish to continue as an admin, you can contact our support team at ${process.env.SUPPORT_MAIL}.\n\n` + |
| 161 | + `Enjoy your new role, and thank you for being a valuable part of the HTh Beats community.\n\n` + |
| 162 | + `Best regards,\n` + |
| 163 | + `The HTh Beats Team`; |
| 164 | + } |
| 165 | + if (type == "user") { |
| 166 | + subject = "Your Admin Role Has Been Revoked on HTh Beats"; |
| 167 | + |
| 168 | + message = |
| 169 | + `Dear ${username},\n\n` + |
| 170 | + `We’d like to inform you that your admin privileges on HTh Beats have been revoked, and your account has been returned to a regular user role.\n\n` + |
| 171 | + `This means you will no longer be able to:\n` + |
| 172 | + `• Approve or deny download requests\n` + |
| 173 | + `• Grant or revoke download access for users\n` + |
| 174 | + `• Add or remove admins\n` + |
| 175 | + `• View administrative statistics or privileged data\n\n` + |
| 176 | + `This decision was made by the HTh Beats Admin Team. We ask you to please respect this decision as part of maintaining the integrity and responsibility expected from admin roles.\n\n` + |
| 177 | + `However, if you believe this action was taken in error or would like clarification, feel free to contact us at ${process.env.SUPPORT_MAIL} and we’ll be happy to assist you.\n\n` + |
| 178 | + `Thank you for your past contributions as an admin. We hope you’ll continue enjoying HTh Beats as a valued user.\n\n` + |
| 179 | + `Sincerely,\n` + |
| 180 | + `The HTh Beats Team`; |
| 181 | + } |
| 182 | + if (!subject || !message) return; |
| 183 | + await utils.sendMail(emails, subject, message); |
| 184 | + const securityMessage = |
| 185 | + `Dear Mahesh,\n\n` + |
| 186 | + `There is new changes in HTh Beats Admin Team as @${username} has been ${ |
| 187 | + type == "admin" ? "added to" : "removed from" |
| 188 | + } the Team. \n\n` + |
| 189 | + `New admin's email: ${emails[0]?.email} \n` + |
| 190 | + `New admin's username: ${emails[0]?.name} \n\n` + |
| 191 | + `The HTh Beats Safety System`; |
| 192 | + await utils.sendMail( |
| 193 | + [{ email: "mkmjnp5@gmail.com", name: "Mahesh" }], |
| 194 | + "Changes in HTh Beats Admin Team", |
| 195 | + securityMessage |
| 196 | + ); |
| 197 | +}; |
| 198 | + |
| 199 | +module.exports = admin; |
0 commit comments