Browse Source

feat: added ability for admins to delete modifiable user playlists

Kristian Vos 3 năm trước cách đây
mục cha
commit
0deddb39f5

+ 74 - 2
backend/logic/actions/playlists.js

@@ -1352,10 +1352,10 @@ export default {
 	}),
 
 	/**
-	 * Removes a private playlist
+	 * Removes a user's own modifiable user playlist
 	 *
 	 * @param {object} session - the session object automatically added by the websocket
-	 * @param {string} playlistId - the id of the playlist we are moving the song to the top from
+	 * @param {string} playlistId - the id of the playlist we are removing
 	 * @param {Function} cb - gets called with the result
 	 */
 	remove: isLoginRequired(async function remove(session, playlistId, cb) {
@@ -1432,6 +1432,78 @@ export default {
 		);
 	}),
 
+	/**
+	 * Removes a user's modifiable user playlist as an admin
+	 *
+	 * @param {object} session - the session object automatically added by the websocket
+	 * @param {string} playlistId - the id of the playlist we are removing
+	 * @param {Function} cb - gets called with the result
+	 */
+	 removeAdmin: isAdminRequired(async function removeAdmin(session, playlistId, cb) {
+		const userModel = await DBModule.runJob("GET_MODEL", { modelName: "user" }, this);
+
+		async.waterfall(
+			[
+				next => {
+					PlaylistsModule.runJob("GET_PLAYLIST", { playlistId }, this)
+						.then(playlist => next(null, playlist))
+						.catch(next);
+				},
+
+				(playlist, next) => {
+					if (!playlist.isUserModifiable) return next("Playlist cannot be removed.");
+					return next(null, playlist);
+				},
+
+				(playlist, next) => {
+					userModel.updateOne(
+						{ _id: playlist.createdBy },
+						{ $pull: { "preferences.orderOfPlaylists": playlist._id } },
+						err => next(err, playlist)
+					);
+				},
+
+				(playlist, next) => {
+					PlaylistsModule.runJob("DELETE_PLAYLIST", { playlistId }, this)
+						.then(() => next(null, playlist))
+						.catch(next);
+				}
+			],
+			async err => {
+				if (err) {
+					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
+					this.log(
+						"ERROR",
+						"PLAYLIST_REMOVE_ADMIN",
+						`Removing private playlist "${playlistId}" failed for user "${session.userId}". "${err}"`
+					);
+					return cb({ status: "error", message: err });
+				}
+
+				this.log(
+					"SUCCESS",
+					"PLAYLIST_REMOVE_ADMIN",
+					`Successfully removed private playlist "${playlistId}" for user "${session.userId}".`
+				);
+
+				CacheModule.runJob("PUB", {
+					channel: "playlist.delete",
+					value: {
+						userId: session.userId,
+						playlistId
+					}
+				});
+
+				ActivitiesModule.runJob("REMOVE_ACTIVITY_REFERENCES", { type: "playlistId", playlistId });
+
+				return cb({
+					status: "success",
+					message: "Playlist successfully removed"
+				});
+			}
+		)
+	 }),
+
 	/**
 	 * Updates the privacy of a private playlist
 	 *

+ 24 - 4
frontend/src/components/modals/EditPlaylist/index.vue

@@ -393,6 +393,9 @@ export default {
 		isAdmin() {
 			return this.userRole === "admin";
 		},
+		isOwner() {
+			return this.loggedIn && this.userId === this.playlist.createdBy;
+		},
 		repositionSong({ moved }) {
 			if (!moved) return; // we only need to update when song is moved
 
@@ -480,10 +483,27 @@ export default {
 			);
 		},
 		removePlaylist() {
-			this.socket.dispatch("playlists.remove", this.playlist._id, res => {
-				new Toast(res.message);
-				if (res.status === "success") this.closeModal("editPlaylist");
-			});
+			if (this.isOwner()) {
+				this.socket.dispatch(
+					"playlists.remove",
+					this.playlist._id,
+					res => {
+						new Toast(res.message);
+						if (res.status === "success")
+							this.closeModal("editPlaylist");
+					}
+				);
+			} else if (this.isAdmin()) {
+				this.socket.dispatch(
+					"playlists.removeAdmin",
+					this.playlist._id,
+					res => {
+						new Toast(res.message);
+						if (res.status === "success")
+							this.closeModal("editPlaylist");
+					}
+				);
+			}
 		},
 		async downloadPlaylist() {
 			if (this.apiDomain === "")