mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-03 00:06:46 +01:00
Update:Only emit library socket events to users with access to lib
This commit is contained in:
parent
725f8eecdb
commit
0e292c64c4
@ -109,7 +109,7 @@ class Auth {
|
|||||||
Logger.error('JWT Verify Token Failed', err)
|
Logger.error('JWT Verify Token Failed', err)
|
||||||
return resolve(null)
|
return resolve(null)
|
||||||
}
|
}
|
||||||
var user = this.users.find(u => u.id === payload.userId && u.username === payload.username)
|
const user = this.users.find(u => u.id === payload.userId && u.username === payload.username)
|
||||||
resolve(user || null)
|
resolve(user || null)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -31,9 +31,13 @@ class SocketAuthority {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emits event to all authorized clients
|
// Emits event to all authorized clients
|
||||||
emitter(evt, data) {
|
// optional filter function to only send event to specific users
|
||||||
|
// TODO: validate that filter is actually a function
|
||||||
|
emitter(evt, data, filter = null) {
|
||||||
for (const socketId in this.clients) {
|
for (const socketId in this.clients) {
|
||||||
if (this.clients[socketId].user) {
|
if (this.clients[socketId].user) {
|
||||||
|
if (filter && !filter(this.clients[socketId].user)) continue
|
||||||
|
|
||||||
this.clients[socketId].socket.emit(evt, data)
|
this.clients[socketId].socket.emit(evt, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class LibraryController {
|
|||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
async create(req, res) {
|
async create(req, res) {
|
||||||
var newLibraryPayload = {
|
const newLibraryPayload = {
|
||||||
...req.body
|
...req.body
|
||||||
}
|
}
|
||||||
if (!newLibraryPayload.name || !newLibraryPayload.folders || !newLibraryPayload.folders.length) {
|
if (!newLibraryPayload.name || !newLibraryPayload.folders || !newLibraryPayload.folders.length) {
|
||||||
@ -26,9 +26,9 @@ class LibraryController {
|
|||||||
f.fullPath = Path.resolve(f.fullPath)
|
f.fullPath = Path.resolve(f.fullPath)
|
||||||
return f
|
return f
|
||||||
})
|
})
|
||||||
for (var folder of newLibraryPayload.folders) {
|
for (const folder of newLibraryPayload.folders) {
|
||||||
try {
|
try {
|
||||||
var direxists = await fs.pathExists(folder.fullPath)
|
const direxists = await fs.pathExists(folder.fullPath)
|
||||||
if (!direxists) { // If folder does not exist try to make it and set file permissions/owner
|
if (!direxists) { // If folder does not exist try to make it and set file permissions/owner
|
||||||
await fs.mkdir(folder.fullPath)
|
await fs.mkdir(folder.fullPath)
|
||||||
await filePerms.setDefault(folder.fullPath)
|
await filePerms.setDefault(folder.fullPath)
|
||||||
@ -39,12 +39,16 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var library = new Library()
|
const library = new Library()
|
||||||
newLibraryPayload.displayOrder = this.db.libraries.length + 1
|
newLibraryPayload.displayOrder = this.db.libraries.length + 1
|
||||||
library.setData(newLibraryPayload)
|
library.setData(newLibraryPayload)
|
||||||
await this.db.insertEntity('library', library)
|
await this.db.insertEntity('library', library)
|
||||||
// TODO: Only emit to users that have access
|
|
||||||
SocketAuthority.emitter('library_added', library.toJSON())
|
// Only emit to users with access to library
|
||||||
|
const userFilter = (user) => {
|
||||||
|
return user.checkCanAccessLibrary && user.checkCanAccessLibrary(library.id)
|
||||||
|
}
|
||||||
|
SocketAuthority.emitter('library_added', library.toJSON(), userFilter)
|
||||||
|
|
||||||
// Add library watcher
|
// Add library watcher
|
||||||
this.watcher.addLibrary(library)
|
this.watcher.addLibrary(library)
|
||||||
@ -53,7 +57,7 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
findAll(req, res) {
|
findAll(req, res) {
|
||||||
var librariesAccessible = req.user.librariesAccessible || []
|
const librariesAccessible = req.user.librariesAccessible || []
|
||||||
if (librariesAccessible && librariesAccessible.length) {
|
if (librariesAccessible && librariesAccessible.length) {
|
||||||
return res.json(this.db.libraries.filter(lib => librariesAccessible.includes(lib.id)).map(lib => lib.toJSON()))
|
return res.json(this.db.libraries.filter(lib => librariesAccessible.includes(lib.id)).map(lib => lib.toJSON()))
|
||||||
}
|
}
|
||||||
@ -75,12 +79,12 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(req, res) {
|
async update(req, res) {
|
||||||
var library = req.library
|
const library = req.library
|
||||||
|
|
||||||
// Validate new folder paths exist or can be created & resolve rel paths
|
// Validate new folder paths exist or can be created & resolve rel paths
|
||||||
// returns 400 if a new folder fails to access
|
// returns 400 if a new folder fails to access
|
||||||
if (req.body.folders) {
|
if (req.body.folders) {
|
||||||
var newFolderPaths = []
|
const newFolderPaths = []
|
||||||
req.body.folders = req.body.folders.map(f => {
|
req.body.folders = req.body.folders.map(f => {
|
||||||
if (!f.id) {
|
if (!f.id) {
|
||||||
f.fullPath = Path.resolve(f.fullPath)
|
f.fullPath = Path.resolve(f.fullPath)
|
||||||
@ -88,11 +92,11 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
})
|
})
|
||||||
for (var path of newFolderPaths) {
|
for (const path of newFolderPaths) {
|
||||||
var pathExists = await fs.pathExists(path)
|
const pathExists = await fs.pathExists(path)
|
||||||
if (!pathExists) {
|
if (!pathExists) {
|
||||||
// Ensure dir will recursively create directories which might be preferred over mkdir
|
// Ensure dir will recursively create directories which might be preferred over mkdir
|
||||||
var success = await fs.ensureDir(path).then(() => true).catch((error) => {
|
const success = await fs.ensureDir(path).then(() => true).catch((error) => {
|
||||||
Logger.error(`[LibraryController] Failed to ensure folder dir "${path}"`, error)
|
Logger.error(`[LibraryController] Failed to ensure folder dir "${path}"`, error)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@ -105,7 +109,7 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasUpdates = library.update(req.body)
|
const hasUpdates = library.update(req.body)
|
||||||
// TODO: Should check if this is an update to folder paths or name only
|
// TODO: Should check if this is an update to folder paths or name only
|
||||||
if (hasUpdates) {
|
if (hasUpdates) {
|
||||||
// Update watcher
|
// Update watcher
|
||||||
@ -115,7 +119,7 @@ class LibraryController {
|
|||||||
this.cronManager.updateLibraryScanCron(library)
|
this.cronManager.updateLibraryScanCron(library)
|
||||||
|
|
||||||
// Remove libraryItems no longer in library
|
// Remove libraryItems no longer in library
|
||||||
var itemsToRemove = this.db.libraryItems.filter(li => li.libraryId === library.id && !library.checkFullPathInLibrary(li.path))
|
const itemsToRemove = this.db.libraryItems.filter(li => li.libraryId === library.id && !library.checkFullPathInLibrary(li.path))
|
||||||
if (itemsToRemove.length) {
|
if (itemsToRemove.length) {
|
||||||
Logger.info(`[Scanner] Updating library, removing ${itemsToRemove.length} items`)
|
Logger.info(`[Scanner] Updating library, removing ${itemsToRemove.length} items`)
|
||||||
for (let i = 0; i < itemsToRemove.length; i++) {
|
for (let i = 0; i < itemsToRemove.length; i++) {
|
||||||
@ -123,32 +127,37 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.db.updateEntity('library', library)
|
await this.db.updateEntity('library', library)
|
||||||
SocketAuthority.emitter('library_updated', library.toJSON())
|
|
||||||
|
// Only emit to users with access to library
|
||||||
|
const userFilter = (user) => {
|
||||||
|
return user.checkCanAccessLibrary && user.checkCanAccessLibrary(library.id)
|
||||||
|
}
|
||||||
|
SocketAuthority.emitter('library_updated', library.toJSON(), userFilter)
|
||||||
}
|
}
|
||||||
return res.json(library.toJSON())
|
return res.json(library.toJSON())
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
var library = req.library
|
const library = req.library
|
||||||
|
|
||||||
// Remove library watcher
|
// Remove library watcher
|
||||||
this.watcher.removeLibrary(library)
|
this.watcher.removeLibrary(library)
|
||||||
|
|
||||||
// Remove collections for library
|
// Remove collections for library
|
||||||
var collections = this.db.collections.filter(c => c.libraryId === library.id)
|
const collections = this.db.collections.filter(c => c.libraryId === library.id)
|
||||||
for (const collection of collections) {
|
for (const collection of collections) {
|
||||||
Logger.info(`[Server] deleting collection "${collection.name}" for library "${library.name}"`)
|
Logger.info(`[Server] deleting collection "${collection.name}" for library "${library.name}"`)
|
||||||
await this.db.removeEntity('collection', collection.id)
|
await this.db.removeEntity('collection', collection.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove items in this library
|
// Remove items in this library
|
||||||
var libraryItems = this.db.libraryItems.filter(li => li.libraryId === library.id)
|
const libraryItems = this.db.libraryItems.filter(li => li.libraryId === library.id)
|
||||||
Logger.info(`[Server] deleting library "${library.name}" with ${libraryItems.length} items"`)
|
Logger.info(`[Server] deleting library "${library.name}" with ${libraryItems.length} items"`)
|
||||||
for (let i = 0; i < libraryItems.length; i++) {
|
for (let i = 0; i < libraryItems.length; i++) {
|
||||||
await this.handleDeleteLibraryItem(libraryItems[i])
|
await this.handleDeleteLibraryItem(libraryItems[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
var libraryJson = library.toJSON()
|
const libraryJson = library.toJSON()
|
||||||
await this.db.removeEntity('library', library.id)
|
await this.db.removeEntity('library', library.id)
|
||||||
SocketAuthority.emitter('library_removed', libraryJson)
|
SocketAuthority.emitter('library_removed', libraryJson)
|
||||||
return res.json(libraryJson)
|
return res.json(libraryJson)
|
||||||
@ -170,10 +179,10 @@ class LibraryController {
|
|||||||
minified: req.query.minified === '1',
|
minified: req.query.minified === '1',
|
||||||
collapseseries: req.query.collapseseries === '1'
|
collapseseries: req.query.collapseseries === '1'
|
||||||
}
|
}
|
||||||
var mediaIsBook = payload.mediaType === 'book'
|
const mediaIsBook = payload.mediaType === 'book'
|
||||||
|
|
||||||
// Step 1 - Filter the retrieved library items
|
// Step 1 - Filter the retrieved library items
|
||||||
var filterSeries = null
|
let filterSeries = null
|
||||||
if (payload.filterBy) {
|
if (payload.filterBy) {
|
||||||
libraryItems = libraryHelpers.getFilteredLibraryItems(libraryItems, payload.filterBy, req.user, this.rssFeedManager.feedsArray)
|
libraryItems = libraryHelpers.getFilteredLibraryItems(libraryItems, payload.filterBy, req.user, this.rssFeedManager.feedsArray)
|
||||||
payload.total = libraryItems.length
|
payload.total = libraryItems.length
|
||||||
@ -216,7 +225,7 @@ class LibraryController {
|
|||||||
|
|
||||||
if (payload.sortBy) {
|
if (payload.sortBy) {
|
||||||
// old sort key TODO: should be mutated in dbMigration
|
// old sort key TODO: should be mutated in dbMigration
|
||||||
var sortKey = payload.sortBy
|
let sortKey = payload.sortBy
|
||||||
if (sortKey.startsWith('book.')) {
|
if (sortKey.startsWith('book.')) {
|
||||||
sortKey = sortKey.replace('book.', 'media.metadata.')
|
sortKey = sortKey.replace('book.', 'media.metadata.')
|
||||||
}
|
}
|
||||||
@ -246,7 +255,7 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort series based on the sortBy attribute
|
// Sort series based on the sortBy attribute
|
||||||
var direction = payload.sortDesc ? 'desc' : 'asc'
|
const direction = payload.sortDesc ? 'desc' : 'asc'
|
||||||
sortArray.push({
|
sortArray.push({
|
||||||
[direction]: (li) => {
|
[direction]: (li) => {
|
||||||
if (mediaIsBook && sortBySequence) {
|
if (mediaIsBook && sortBySequence) {
|
||||||
@ -332,7 +341,7 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async removeLibraryItemsWithIssues(req, res) {
|
async removeLibraryItemsWithIssues(req, res) {
|
||||||
var libraryItemsWithIssues = req.libraryItems.filter(li => li.hasIssues)
|
const libraryItemsWithIssues = req.libraryItems.filter(li => li.hasIssues)
|
||||||
if (!libraryItemsWithIssues.length) {
|
if (!libraryItemsWithIssues.length) {
|
||||||
Logger.warn(`[LibraryController] No library items have issues`)
|
Logger.warn(`[LibraryController] No library items have issues`)
|
||||||
return res.sendStatus(200)
|
return res.sendStatus(200)
|
||||||
@ -349,8 +358,8 @@ class LibraryController {
|
|||||||
|
|
||||||
// api/libraries/:id/series
|
// api/libraries/:id/series
|
||||||
async getAllSeriesForLibrary(req, res) {
|
async getAllSeriesForLibrary(req, res) {
|
||||||
var libraryItems = req.libraryItems
|
const libraryItems = req.libraryItems
|
||||||
var payload = {
|
const payload = {
|
||||||
results: [],
|
results: [],
|
||||||
total: 0,
|
total: 0,
|
||||||
limit: req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 0,
|
limit: req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 0,
|
||||||
@ -361,7 +370,7 @@ class LibraryController {
|
|||||||
minified: req.query.minified === '1'
|
minified: req.query.minified === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
var series = libraryHelpers.getSeriesFromBooks(libraryItems, this.db.series, null, payload.filterBy, req.user, payload.minified)
|
let series = libraryHelpers.getSeriesFromBooks(libraryItems, this.db.series, null, payload.filterBy, req.user, payload.minified)
|
||||||
|
|
||||||
const direction = payload.sortDesc ? 'desc' : 'asc'
|
const direction = payload.sortDesc ? 'desc' : 'asc'
|
||||||
series = naturalSort(series).by([
|
series = naturalSort(series).by([
|
||||||
|
Loading…
Reference in New Issue
Block a user