Merge pull request #4200 from advplyr/socket_item_events

Fix socket events check user permissions for library items #4199
This commit is contained in:
advplyr 2025-04-12 17:48:22 -05:00 committed by GitHub
commit 7764f1cf75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 69 additions and 61 deletions

View file

@ -84,6 +84,42 @@ class SocketAuthority {
}
}
/**
* Emits event with library item to all clients that can access the library item
* Note: Emits toOldJSONExpanded()
*
* @param {string} evt
* @param {import('./models/LibraryItem')} libraryItem
*/
libraryItemEmitter(evt, libraryItem) {
for (const socketId in this.clients) {
if (this.clients[socketId].user?.checkCanAccessLibraryItem(libraryItem)) {
this.clients[socketId].socket.emit(evt, libraryItem.toOldJSONExpanded())
}
}
}
/**
* Emits event with library items to all clients that can access the library items
* Note: Emits toOldJSONExpanded()
*
* @param {string} evt
* @param {import('./models/LibraryItem')[]} libraryItems
*/
libraryItemsEmitter(evt, libraryItems) {
for (const socketId in this.clients) {
if (this.clients[socketId].user) {
const libraryItemsAccessibleToUser = libraryItems.filter((li) => this.clients[socketId].user.checkCanAccessLibraryItem(li))
if (libraryItemsAccessibleToUser.length) {
this.clients[socketId].socket.emit(
evt,
libraryItemsAccessibleToUser.map((li) => li.toOldJSONExpanded())
)
}
}
}
}
/**
* Closes the Socket.IO server and disconnect all clients
*

View file

@ -152,10 +152,7 @@ class AuthorController {
for (const libraryItem of libraryItems) {
await libraryItem.saveMetadataFile()
}
SocketAuthority.emitter(
'items_updated',
libraryItems.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_updated', libraryItems)
}
// Remove old author
@ -210,10 +207,7 @@ class AuthorController {
}
if (libraryItems.length) {
SocketAuthority.emitter(
'items_updated',
libraryItems.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_updated', libraryItems)
}
} else {
numBooksForAuthor = await Database.bookAuthorModel.getCountForAuthor(req.author.id)

View file

@ -1188,10 +1188,7 @@ class LibraryController {
}
if (itemsUpdated.length) {
SocketAuthority.emitter(
'items_updated',
itemsUpdated.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_updated', itemsUpdated)
}
res.json({
@ -1232,10 +1229,7 @@ class LibraryController {
}
if (itemsUpdated.length) {
SocketAuthority.emitter(
'items_updated',
itemsUpdated.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_updated', itemsUpdated)
}
res.json({

View file

@ -253,7 +253,7 @@ class LibraryItemController {
}
Logger.debug(`[LibraryItemController] Updated library item media ${req.libraryItem.media.title}`)
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
}
res.json({
updated: hasUpdates,
@ -300,7 +300,7 @@ class LibraryItemController {
req.libraryItem.changed('updatedAt', true)
await req.libraryItem.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
res.json({
success: true,
cover: result.cover
@ -332,7 +332,7 @@ class LibraryItemController {
req.libraryItem.changed('updatedAt', true)
await req.libraryItem.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
}
res.json({
success: true,
@ -358,7 +358,7 @@ class LibraryItemController {
await CacheManager.purgeCoverCache(req.libraryItem.id)
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
}
res.sendStatus(200)
@ -485,7 +485,7 @@ class LibraryItemController {
req.libraryItem.media.changed('audioFiles', true)
await req.libraryItem.media.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
res.json(req.libraryItem.toOldJSON())
}
@ -663,7 +663,7 @@ class LibraryItemController {
await libraryItem.saveMetadataFile()
Logger.debug(`[LibraryItemController] Updated library item media "${libraryItem.media.title}"`)
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
itemsUpdated++
}
}
@ -894,7 +894,7 @@ class LibraryItemController {
await req.libraryItem.saveMetadataFile()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
}
res.json({
@ -1005,7 +1005,7 @@ class LibraryItemController {
await req.libraryItem.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
res.sendStatus(200)
}
@ -1153,7 +1153,7 @@ class LibraryItemController {
await req.libraryItem.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
res.sendStatus(200)
}

View file

@ -343,7 +343,7 @@ class MiscController {
})
await libraryItem.saveMetadataFile()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
numItemsUpdated++
}
}
@ -386,7 +386,7 @@ class MiscController {
})
await libraryItem.saveMetadataFile()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
numItemsUpdated++
}
@ -481,7 +481,7 @@ class MiscController {
})
await libraryItem.saveMetadataFile()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
numItemsUpdated++
}
}
@ -524,7 +524,7 @@ class MiscController {
})
await libraryItem.saveMetadataFile()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
numItemsUpdated++
}

View file

@ -161,7 +161,7 @@ class PodcastController {
}
}
SocketAuthority.emitter('item_added', newLibraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_added', newLibraryItem)
res.json(newLibraryItem.toOldJSONExpanded())
@ -379,7 +379,7 @@ class PodcastController {
const overrideDetails = req.query.override === '1'
const episodesUpdated = await Scanner.quickMatchPodcastEpisodes(req.libraryItem, { overrideDetails })
if (episodesUpdated) {
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
}
res.json({
@ -418,7 +418,7 @@ class PodcastController {
Logger.info(`[PodcastController] Updated episode "${episode.title}" keys`, episode.changed())
await episode.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
} else {
Logger.info(`[PodcastController] No changes to episode "${episode.title}"`)
}
@ -504,7 +504,7 @@ class PodcastController {
req.libraryItem.media.numEpisodes = req.libraryItem.media.podcastEpisodes.length
await req.libraryItem.media.save()
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', req.libraryItem)
res.json(req.libraryItem.toOldJSON())
}

View file

@ -254,7 +254,7 @@ class PodcastManager {
await libraryItem.media.save()
}
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
const podcastEpisodeExpanded = podcastEpisode.toOldJSONExpanded(libraryItem.id)
podcastEpisodeExpanded.libraryItem = libraryItem.toOldJSONExpanded()
SocketAuthority.emitter('episode_added', podcastEpisodeExpanded)
@ -367,7 +367,7 @@ class PodcastManager {
libraryItem.changed('updatedAt', true)
await libraryItem.save()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
return libraryItem.media.autoDownloadEpisodes
}
@ -425,7 +425,7 @@ class PodcastManager {
libraryItem.changed('updatedAt', true)
await libraryItem.save()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
return newEpisodes || []
}
@ -712,7 +712,7 @@ class PodcastManager {
}
}
SocketAuthority.emitter('item_added', newLibraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_added', newLibraryItem)
// Turn on podcast auto download cron if not already on
if (newLibraryItem.media.autoDownloadEpisodes) {

View file

@ -64,7 +64,7 @@ class LibraryItemScanner {
const { libraryItem: expandedLibraryItem, wasUpdated } = await this.rescanLibraryItemMedia(libraryItem, libraryItemScanData, library.settings, scanLogger)
if (libraryItemDataUpdated || wasUpdated) {
SocketAuthority.emitter('item_updated', expandedLibraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', expandedLibraryItem)
await this.checkAuthorsAndSeriesRemovedFromBooks(library.id, scanLogger)

View file

@ -223,11 +223,7 @@ class LibraryScanner {
// Emit item updates in chunks of 10 to client
if (libraryItemsUpdated.length === 10) {
// TODO: Should only emit to clients where library item is accessible
SocketAuthority.emitter(
'items_updated',
libraryItemsUpdated.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_updated', libraryItemsUpdated)
libraryItemsUpdated = []
}
@ -235,11 +231,7 @@ class LibraryScanner {
}
// Emit item updates to client
if (libraryItemsUpdated.length) {
// TODO: Should only emit to clients where library item is accessible
SocketAuthority.emitter(
'items_updated',
libraryItemsUpdated.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_updated', libraryItemsUpdated)
}
// Authors and series that were removed from books should be removed if they are now empty
@ -277,11 +269,7 @@ class LibraryScanner {
// Emit new items in chunks of 10 to client
if (newLibraryItems.length === 10) {
// TODO: Should only emit to clients where library item is accessible
SocketAuthority.emitter(
'items_added',
newLibraryItems.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_added', newLibraryItems)
newLibraryItems = []
}
@ -289,11 +277,7 @@ class LibraryScanner {
}
// Emit new items to client
if (newLibraryItems.length) {
// TODO: Should only emit to clients where library item is accessible
SocketAuthority.emitter(
'items_added',
newLibraryItems.map((li) => li.toOldJSONExpanded())
)
SocketAuthority.libraryItemsEmitter('items_added', newLibraryItems)
}
}
@ -609,7 +593,7 @@ class LibraryScanner {
Logger.info(`[LibraryScanner] Scanning file update group and library item was deleted "${existingLibraryItem.media.title}" - marking as missing`)
existingLibraryItem.isMissing = true
await existingLibraryItem.save()
SocketAuthority.emitter('item_updated', existingLibraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', existingLibraryItem)
itemGroupingResults[itemDir] = ScanResult.REMOVED
continue
@ -643,7 +627,7 @@ class LibraryScanner {
const isSingleMediaItem = isSingleMediaFile(fileUpdateGroup, itemDir)
const newLibraryItem = await LibraryItemScanner.scanPotentialNewLibraryItem(fullPath, library, folder, isSingleMediaItem)
if (newLibraryItem) {
SocketAuthority.emitter('item_added', newLibraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_added', newLibraryItem)
}
itemGroupingResults[itemDir] = newLibraryItem ? ScanResult.ADDED : ScanResult.NOTHING
}

View file

@ -126,7 +126,7 @@ class Scanner {
await libraryItem.saveMetadataFile()
SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
SocketAuthority.libraryItemEmitter('item_updated', libraryItem)
}
return {