From e61d9deb52bc33b1f77aaf153f645cf3d55b25c1 Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Fri, 4 Apr 2025 20:38:40 -0400 Subject: [PATCH] Fixed perms for schedule/channel playlists --- src/app/channel/media/playlistHandler.js | 314 +++++++++--------- src/app/channel/media/queue.js | 46 +-- .../channel/channelPermissionSchema.js | 6 + 3 files changed, 197 insertions(+), 169 deletions(-) diff --git a/src/app/channel/media/playlistHandler.js b/src/app/channel/media/playlistHandler.js index 73c400b..ab20170 100644 --- a/src/app/channel/media/playlistHandler.js +++ b/src/app/channel/media/playlistHandler.js @@ -66,49 +66,50 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - - //If the title is too long - if(!validator.isLength(data.playlist, {max:30})){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, "Playlist name too long!", "validation"); - //and ignore it! - return; - } - - //Escape/trim the playlist name - const name = validator.escape(validator.trim(data.playlist)); - - //If the channel already exists - if(chanDB.getPlaylistByName(name) != null){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, `Playlist named '${name}' already exists!`, "validation"); - //and ignore it! - return; - } - - //Create empty array to hold titles - const safeTitles = []; - - //For each default title passed by the data - for(let title of data.defaultTitles){ - //If the title isn't too long - if(validator.isLength(title, {min:1, max:30})){ - //Add it to the safe title list - safeTitles.push(validator.escape(validator.trim(title))) + if(await chanDB.permCheck(socket.user, 'editChannelPlaylists')){ + //If the title is too long + if(!validator.isLength(data.playlist, {max:30})){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, "Playlist name too long!", "validation"); + //and ignore it! + return; } + + //Escape/trim the playlist name + const name = validator.escape(validator.trim(data.playlist)); + + //If the channel already exists + if(chanDB.getPlaylistByName(name) != null){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, `Playlist named '${name}' already exists!`, "validation"); + //and ignore it! + return; + } + + //Create empty array to hold titles + const safeTitles = []; + + //For each default title passed by the data + for(let title of data.defaultTitles){ + //If the title isn't too long + if(validator.isLength(title, {min:1, max:30})){ + //Add it to the safe title list + safeTitles.push(validator.escape(validator.trim(title))) + } + } + + //Add playlist to the channel doc + chanDB.media.playlists.push({ + name, + defaultTitles: safeTitles + }); + + //Save the channel doc + await chanDB.save(); + + //Return playlists from channel doc + socket.emit('chanPlaylists', chanDB.getPlaylists()); } - - //Add playlist to the channel doc - chanDB.media.playlists.push({ - name, - defaultTitles: safeTitles - }); - - //Save the channel doc - await chanDB.save(); - - //Return playlists from channel doc - socket.emit('chanPlaylists', chanDB.getPlaylists()); }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } @@ -122,11 +123,13 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - //Delete playlist name - await chanDB.deletePlaylistByName(data.playlist); + if(await chanDB.permCheck(socket.user, 'editChannelPlaylists')){ + //Delete playlist name + await chanDB.deletePlaylistByName(data.playlist); - //Return playlists from channel doc - socket.emit('chanPlaylists', chanDB.getPlaylists()); + //Return playlists from channel doc + socket.emit('chanPlaylists', chanDB.getPlaylists()); + } }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } @@ -140,38 +143,40 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - let url = data.url + if(await chanDB.permCheck(socket.user, 'editChannelPlaylists')){ + let url = data.url - //If we where given a bad URL - if(!validator.isURL(url)){ - //Attempt to fix the situation by encoding it - url = encodeURI(url); - - //If it's still bad + //If we where given a bad URL if(!validator.isURL(url)){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, "Bad URL!", "validation"); - //and ignore it! - return; + //Attempt to fix the situation by encoding it + url = encodeURI(url); + + //If it's still bad + if(!validator.isURL(url)){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, "Bad URL!", "validation"); + //and ignore it! + return; + } } + + //Pull media metadata + let mediaList = await yanker.yankMedia(url); + + //If we didn't get any media + if(mediaList.length == 0 || mediaList == null){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, "No media found!", "queue"); + //and ignore it! + return; + } + + //Add media object to the given playlist + await chanDB.addToPlaylist(data.playlist, mediaList[0]); + + //Return playlists from channel doc + socket.emit('chanPlaylists', chanDB.getPlaylists()); } - - //Pull media metadata - let mediaList = await yanker.yankMedia(url); - - //If we didn't get any media - if(mediaList.length == 0 || mediaList == null){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, "No media found!", "queue"); - //and ignore it! - return; - } - - //Add media object to the given playlist - await chanDB.addToPlaylist(data.playlist, mediaList[0]); - - //Return playlists from channel doc - socket.emit('chanPlaylists', chanDB.getPlaylists()); }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } @@ -185,29 +190,32 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - //Pull a valid start time from input, or make one up if we can't - let start = this.channel.queue.getStart(data.start); + //Permcheck to make sure the user can fuck w/ the queue + if((!this.channel.queue.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin')){ + //Pull a valid start time from input, or make one up if we can't + let start = this.channel.queue.getStart(data.start); - //Grab playlist from the DB - let playlist = chanDB.getPlaylistByName(data.playlist); + //Grab playlist from the DB + let playlist = chanDB.getPlaylistByName(data.playlist); - //Create an empty array to hold our media list - const mediaList = []; + //Create an empty array to hold our media list + const mediaList = []; - //Iterate through playlist media - for(let item of playlist.media){ - //Rehydrate a full phat media object from the flat DB entry - let mediaObj = item.rehydrate(); + //Iterate through playlist media + for(let item of playlist.media){ + //Rehydrate a full phat media object from the flat DB entry + let mediaObj = item.rehydrate(); - //Set media title from default titles - mediaObj.title = playlist.defaultTitles[Math.floor(Math.random() * playlist.defaultTitles.length)]; + //Set media title from default titles + mediaObj.title = playlist.defaultTitles[Math.floor(Math.random() * playlist.defaultTitles.length)]; - //Push rehydrated item on to the mediaList - mediaList.push(mediaObj); + //Push rehydrated item on to the mediaList + mediaList.push(mediaObj); + } + + //Convert array of standard media objects to queued media objects, and push to schedule + this.channel.queue.scheduleMedia(queuedMedia.fromMediaArray(mediaList, start), socket, chanDB); } - - //Convert array of standard media objects to queued media objects, and push to schedule - this.channel.queue.scheduleMedia(queuedMedia.fromMediaArray(mediaList, start), socket, chanDB); }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } @@ -221,36 +229,38 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - //If the title is too long - if(!validator.isLength(data.name, {max:30})){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, "Playlist name too long!", "validation"); - //and ignore it! - return; + if(await chanDB.permCheck(socket.user, 'editChannelPlaylists')){ + //If the title is too long + if(!validator.isLength(data.name, {max:30})){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, "Playlist name too long!", "validation"); + //and ignore it! + return; + } + + //Escape/trim the playlist name + const name = validator.escape(validator.trim(data.name)); + + //If the channel already exists + if(chanDB.getPlaylistByName(name) != null){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, `Playlist named '${name}' already exists!`, "validation"); + //and ignore it! + return; + } + + //Find playlist + let playlist = chanDB.getPlaylistByName(data.playlist); + + //Change playlist name + chanDB.media.playlists[playlist.listIndex].name = name; + + //Save channel document + await chanDB.save(); + + //Return playlists from channel doc + socket.emit('chanPlaylists', chanDB.getPlaylists()); } - - //Escape/trim the playlist name - const name = validator.escape(validator.trim(data.name)); - - //If the channel already exists - if(chanDB.getPlaylistByName(name) != null){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, `Playlist named '${name}' already exists!`, "validation"); - //and ignore it! - return; - } - - //Find playlist - let playlist = chanDB.getPlaylistByName(data.playlist); - - //Change playlist name - chanDB.media.playlists[playlist.listIndex].name = name; - - //Save channel document - await chanDB.save(); - - //Return playlists from channel doc - socket.emit('chanPlaylists', chanDB.getPlaylists()); }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } @@ -264,29 +274,31 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - //Find playlist - let playlist = chanDB.getPlaylistByName(data.playlist); + if(await chanDB.permCheck(socket.user, 'editChannelPlaylists')){ + //Find playlist + let playlist = chanDB.getPlaylistByName(data.playlist); - //Create empty array to hold titles - const safeTitles = []; + //Create empty array to hold titles + const safeTitles = []; - //For each default title passed by the data - for(let title of data.defaultTitles){ - //If the title isn't too long or too short - if(validator.isLength(title, {min: 1, max:30})){ - //Add it to the safe title list - safeTitles.push(validator.escape(validator.trim(title))) + //For each default title passed by the data + for(let title of data.defaultTitles){ + //If the title isn't too long or too short + if(validator.isLength(title, {min: 1, max:30})){ + //Add it to the safe title list + safeTitles.push(validator.escape(validator.trim(title))) + } } + + //Change playlist name + chanDB.media.playlists[playlist.listIndex].defaultTitles = safeTitles; + + //Save channel document + await chanDB.save(); + + //Return playlists from channel doc + socket.emit('chanPlaylists', chanDB.getPlaylists()); } - - //Change playlist name - chanDB.media.playlists[playlist.listIndex].defaultTitles = safeTitles; - - //Save channel document - await chanDB.save(); - - //Return playlists from channel doc - socket.emit('chanPlaylists', chanDB.getPlaylists()); }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } @@ -300,19 +312,21 @@ module.exports = class{ chanDB = await channelModel.findOne({name: this.channel.name}); } - //If we don't have a valid UUID - if(!validator.isUUID(data.uuid)){ - //Bitch, moan, complain... - loggerUtils.socketErrorHandler(socket, `'${data.uuid}' is not a valid UUID!`, "validation"); - //and ignore it! - return; + if(await chanDB.permCheck(socket.user, 'editChannelPlaylists')){ + //If we don't have a valid UUID + if(!validator.isUUID(data.uuid)){ + //Bitch, moan, complain... + loggerUtils.socketErrorHandler(socket, `'${data.uuid}' is not a valid UUID!`, "validation"); + //and ignore it! + return; + } + + //Delete media from channel playlist + chanDB.deletePlaylistMediaByUUID(data.playlist, data.uuid); + + //Return playlists from channel doc + socket.emit('chanPlaylists', chanDB.getPlaylists()); } - - //Delete media from channel playlist - chanDB.deletePlaylistMediaByUUID(data.playlist, data.uuid); - - //Return playlists from channel doc - socket.emit('chanPlaylists', chanDB.getPlaylists()); }catch(err){ return loggerUtils.socketExceptionHandler(socket, err); } diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js index bc21bcb..eda6eb4 100644 --- a/src/app/channel/media/queue.js +++ b/src/app/channel/media/queue.js @@ -54,7 +54,7 @@ module.exports = class{ defineListeners(socket){ socket.on("queue", (data) => {this.queueURL(socket, data)}); - socket.on("stop", (data) => {this.stopMedia(socket)}); + socket.on("stop", (data) => {this.stopMedia(socket)}); //needs perms socket.on("delete", (data) => {this.deleteMedia(socket, data)}); socket.on("clear", (data) => {this.deleteRange(socket, data)}); socket.on("move", (data) => {this.moveMedia(socket, data)}); @@ -121,27 +121,35 @@ module.exports = class{ } } - stopMedia(socket){ - //If we're not currently playing anything - if(this.nowPlaying == null){ - //If an originating socket was provided for this request - if(socket != null){ - //Yell at the user for being an asshole - loggerUtils.socketErrorHandler(socket, "No media playing!", "queue"); + async stopMedia(socket){ + //Get the current channel from the database + const chanDB = await channelModel.findOne({name: socket.chan}); + + console.log(!this.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin'); + //Permcheck to make sure the user can fuck w/ the queue + if((!this.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin')){ + + //If we're not currently playing anything + if(this.nowPlaying == null){ + //If an originating socket was provided for this request + if(socket != null){ + //Yell at the user for being an asshole + loggerUtils.socketErrorHandler(socket, "No media playing!", "queue"); + } + + //Ignore it + return false; } - //Ignore it - return false; + //Stop playing + const stoppedMedia = this.nowPlaying; + + //Get difference between current time and start time and set as early end + stoppedMedia.earlyEnd = (new Date().getTime() - stoppedMedia.startTime) / 1000; + + //End the media + this.end(); } - - //Stop playing - const stoppedMedia = this.nowPlaying; - - //Get difference between current time and start time and set as early end - stoppedMedia.earlyEnd = (new Date().getTime() - stoppedMedia.startTime) / 1000; - - //End the media - this.end(); } async deleteMedia(socket, data){ diff --git a/src/schemas/channel/channelPermissionSchema.js b/src/schemas/channel/channelPermissionSchema.js index 561f982..824b5e2 100644 --- a/src/schemas/channel/channelPermissionSchema.js +++ b/src/schemas/channel/channelPermissionSchema.js @@ -100,6 +100,12 @@ const channelPermissionSchema = new mongoose.Schema({ default: "admin", required: true }, + editChannelPlaylists:{ + type: mongoose.SchemaTypes.String, + enum: rankEnum, + default: "admin", + required: true + }, deleteChannel: { type: mongoose.SchemaTypes.String, enum: rankEnum,