mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-14 17:29:35 +01:00
Update API JS docs
This commit is contained in:
parent
2472b86284
commit
e53ac6566b
@ -390,16 +390,6 @@ class Database {
|
|||||||
return this.models.user.updateFromOld(oldUser)
|
return this.models.user.updateFromOld(oldUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeUser(userId) {
|
|
||||||
if (!this.sequelize) return false
|
|
||||||
return this.models.user.removeById(userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
upsertMediaProgress(oldMediaProgress) {
|
|
||||||
if (!this.sequelize) return false
|
|
||||||
return this.models.mediaProgress.upsertFromOld(oldMediaProgress)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateBulkBooks(oldBooks) {
|
updateBulkBooks(oldBooks) {
|
||||||
if (!this.sequelize) return false
|
if (!this.sequelize) return false
|
||||||
return Promise.all(oldBooks.map((oldBook) => this.models.book.saveFromOld(oldBook)))
|
return Promise.all(oldBooks.map((oldBook) => this.models.book.saveFromOld(oldBook)))
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const { Request, Response, NextFunction } = require('express')
|
||||||
const sequelize = require('sequelize')
|
const sequelize = require('sequelize')
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
const { createNewSortInstance } = require('../libs/fastSort')
|
const { createNewSortInstance } = require('../libs/fastSort')
|
||||||
@ -14,9 +15,23 @@ const { reqSupportsWebp, isValidASIN } = require('../utils/index')
|
|||||||
const naturalSort = createNewSortInstance({
|
const naturalSort = createNewSortInstance({
|
||||||
comparer: new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare
|
comparer: new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class AuthorController {
|
class AuthorController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET: /api/authors/:id
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async findOne(req, res) {
|
async findOne(req, res) {
|
||||||
const include = (req.query.include || '').split(',')
|
const include = (req.query.include || '').split(',')
|
||||||
|
|
||||||
@ -63,9 +78,10 @@ class AuthorController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* PATCH: /api/authors/:id
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async update(req, res) {
|
async update(req, res) {
|
||||||
const payload = req.body
|
const payload = req.body
|
||||||
@ -194,8 +210,8 @@ class AuthorController {
|
|||||||
* DELETE: /api/authors/:id
|
* DELETE: /api/authors/:id
|
||||||
* Remove author from all books and delete
|
* Remove author from all books and delete
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
Logger.info(`[AuthorController] Removing author "${req.author.name}"`)
|
Logger.info(`[AuthorController] Removing author "${req.author.name}"`)
|
||||||
@ -218,8 +234,8 @@ class AuthorController {
|
|||||||
* POST: /api/authors/:id/image
|
* POST: /api/authors/:id/image
|
||||||
* Upload author image from web URL
|
* Upload author image from web URL
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async uploadImage(req, res) {
|
async uploadImage(req, res) {
|
||||||
if (!req.user.canUpload) {
|
if (!req.user.canUpload) {
|
||||||
@ -263,8 +279,8 @@ class AuthorController {
|
|||||||
* DELETE: /api/authors/:id/image
|
* DELETE: /api/authors/:id/image
|
||||||
* Remove author image & delete image file
|
* Remove author image & delete image file
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async deleteImage(req, res) {
|
async deleteImage(req, res) {
|
||||||
if (!req.author.imagePath) {
|
if (!req.author.imagePath) {
|
||||||
@ -284,6 +300,12 @@ class AuthorController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: /api/authors/:id/match
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async match(req, res) {
|
async match(req, res) {
|
||||||
let authorData = null
|
let authorData = null
|
||||||
const region = req.body.region || 'us'
|
const region = req.body.region || 'us'
|
||||||
@ -334,7 +356,12 @@ class AuthorController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/authors/:id/image
|
/**
|
||||||
|
* GET: /api/authors/:id/image
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async getImage(req, res) {
|
async getImage(req, res) {
|
||||||
const {
|
const {
|
||||||
query: { width, height, format, raw },
|
query: { width, height, format, raw },
|
||||||
@ -358,6 +385,12 @@ class AuthorController {
|
|||||||
return CacheManager.handleAuthorCache(res, author, options)
|
return CacheManager.handleAuthorCache(res, author, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
*/
|
||||||
async middleware(req, res, next) {
|
async middleware(req, res, next) {
|
||||||
const author = await Database.authorModel.getOldById(req.params.id)
|
const author = await Database.authorModel.getOldById(req.params.id)
|
||||||
if (!author) return res.sendStatus(404)
|
if (!author) return res.sendStatus(404)
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
|
const { Request, Response, NextFunction } = require('express')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
const fileUtils = require('../utils/fileUtils')
|
const fileUtils = require('../utils/fileUtils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class BackupController {
|
class BackupController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET: /api/backups
|
||||||
|
*
|
||||||
|
* @this import('../routers/ApiRouter')
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
getAll(req, res) {
|
getAll(req, res) {
|
||||||
res.json({
|
res.json({
|
||||||
backups: this.backupManager.backups.map((b) => b.toJSON()),
|
backups: this.backupManager.backups.map((b) => b.toJSON()),
|
||||||
@ -15,10 +31,26 @@ class BackupController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: /api/backups
|
||||||
|
*
|
||||||
|
* @this import('../routers/ApiRouter')
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
create(req, res) {
|
create(req, res) {
|
||||||
this.backupManager.requestCreateBackup(res)
|
this.backupManager.requestCreateBackup(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE: /api/backups/:id
|
||||||
|
*
|
||||||
|
* @this import('../routers/ApiRouter')
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
await this.backupManager.removeBackup(req.backup)
|
await this.backupManager.removeBackup(req.backup)
|
||||||
|
|
||||||
@ -27,6 +59,14 @@ class BackupController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: /api/backups/upload
|
||||||
|
*
|
||||||
|
* @this import('../routers/ApiRouter')
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
upload(req, res) {
|
upload(req, res) {
|
||||||
if (!req.files.file) {
|
if (!req.files.file) {
|
||||||
Logger.error('[BackupController] Upload backup invalid')
|
Logger.error('[BackupController] Upload backup invalid')
|
||||||
@ -41,8 +81,8 @@ class BackupController {
|
|||||||
*
|
*
|
||||||
* @this import('../routers/ApiRouter')
|
* @this import('../routers/ApiRouter')
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async updatePath(req, res) {
|
async updatePath(req, res) {
|
||||||
// Validate path is not empty and is a string
|
// Validate path is not empty and is a string
|
||||||
@ -86,10 +126,10 @@ class BackupController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* api/backups/:id/download
|
* GET: /api/backups/:id/download
|
||||||
*
|
*
|
||||||
* @param {*} req
|
* @param {RequestWithUser} req
|
||||||
* @param {*} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
download(req, res) {
|
download(req, res) {
|
||||||
if (global.XAccel) {
|
if (global.XAccel) {
|
||||||
@ -104,14 +144,23 @@ class BackupController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* GET: /api/backups/:id/apply
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @this import('../routers/ApiRouter')
|
||||||
* @param {import('express').Response} res
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
apply(req, res) {
|
apply(req, res) {
|
||||||
this.backupManager.requestApplyBackup(this.apiCacheManager, req.backup, res)
|
this.backupManager.requestApplyBackup(this.apiCacheManager, req.backup, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
*/
|
||||||
middleware(req, res, next) {
|
middleware(req, res, next) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
Logger.error(`[BackupController] Non-admin user "${req.user.username}" attempting to access backups`)
|
Logger.error(`[BackupController] Non-admin user "${req.user.username}" attempting to access backups`)
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
|
const { Request, Response } = require('express')
|
||||||
const CacheManager = require('../managers/CacheManager')
|
const CacheManager = require('../managers/CacheManager')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class CacheController {
|
class CacheController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
// POST: api/cache/purge
|
/**
|
||||||
|
* POST: /api/cache/purge
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async purgeCache(req, res) {
|
async purgeCache(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
@ -12,7 +25,12 @@ class CacheController {
|
|||||||
res.sendStatus(200)
|
res.sendStatus(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: api/cache/items/purge
|
/**
|
||||||
|
* POST: /api/cache/items/purge
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async purgeItemsCache(req, res) {
|
async purgeItemsCache(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const { Request, Response, NextFunction } = require('express')
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const SocketAuthority = require('../SocketAuthority')
|
const SocketAuthority = require('../SocketAuthority')
|
||||||
@ -5,14 +6,22 @@ const Database = require('../Database')
|
|||||||
|
|
||||||
const Collection = require('../objects/Collection')
|
const Collection = require('../objects/Collection')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class CollectionController {
|
class CollectionController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST: /api/collections
|
* POST: /api/collections
|
||||||
* Create new collection
|
* Create new collection
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async create(req, res) {
|
async create(req, res) {
|
||||||
const newCollection = new Collection()
|
const newCollection = new Collection()
|
||||||
@ -49,6 +58,12 @@ class CollectionController {
|
|||||||
res.json(jsonExpanded)
|
res.json(jsonExpanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET: /api/collections
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async findAll(req, res) {
|
async findAll(req, res) {
|
||||||
const collectionsExpanded = await Database.collectionModel.getOldCollectionsJsonExpanded(req.user)
|
const collectionsExpanded = await Database.collectionModel.getOldCollectionsJsonExpanded(req.user)
|
||||||
res.json({
|
res.json({
|
||||||
@ -56,6 +71,12 @@ class CollectionController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET: /api/collections/:id
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async findOne(req, res) {
|
async findOne(req, res) {
|
||||||
const includeEntities = (req.query.include || '').split(',')
|
const includeEntities = (req.query.include || '').split(',')
|
||||||
|
|
||||||
@ -71,8 +92,9 @@ class CollectionController {
|
|||||||
/**
|
/**
|
||||||
* PATCH: /api/collections/:id
|
* PATCH: /api/collections/:id
|
||||||
* Update collection
|
* Update collection
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async update(req, res) {
|
async update(req, res) {
|
||||||
let wasUpdated = false
|
let wasUpdated = false
|
||||||
@ -123,6 +145,12 @@ class CollectionController {
|
|||||||
res.json(jsonExpanded)
|
res.json(jsonExpanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE: /api/collections/:id
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
const jsonExpanded = await req.collection.getOldJsonExpanded()
|
const jsonExpanded = await req.collection.getOldJsonExpanded()
|
||||||
|
|
||||||
@ -139,8 +167,9 @@ class CollectionController {
|
|||||||
* POST: /api/collections/:id/book
|
* POST: /api/collections/:id/book
|
||||||
* Add a single book to a collection
|
* Add a single book to a collection
|
||||||
* Req.body { id: <library item id> }
|
* Req.body { id: <library item id> }
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async addBook(req, res) {
|
async addBook(req, res) {
|
||||||
const libraryItem = await Database.libraryItemModel.getOldById(req.body.id)
|
const libraryItem = await Database.libraryItemModel.getOldById(req.body.id)
|
||||||
@ -172,8 +201,9 @@ class CollectionController {
|
|||||||
* DELETE: /api/collections/:id/book/:bookId
|
* DELETE: /api/collections/:id/book/:bookId
|
||||||
* Remove a single book from a collection. Re-order books
|
* Remove a single book from a collection. Re-order books
|
||||||
* TODO: bookId is actually libraryItemId. Clients need updating to use bookId
|
* TODO: bookId is actually libraryItemId. Clients need updating to use bookId
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async removeBook(req, res) {
|
async removeBook(req, res) {
|
||||||
const libraryItem = await Database.libraryItemModel.getOldById(req.params.bookId)
|
const libraryItem = await Database.libraryItemModel.getOldById(req.params.bookId)
|
||||||
@ -216,8 +246,9 @@ class CollectionController {
|
|||||||
* POST: /api/collections/:id/batch/add
|
* POST: /api/collections/:id/batch/add
|
||||||
* Add multiple books to collection
|
* Add multiple books to collection
|
||||||
* Req.body { books: <Array of library item ids> }
|
* Req.body { books: <Array of library item ids> }
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async addBatch(req, res) {
|
async addBatch(req, res) {
|
||||||
// filter out invalid libraryItemIds
|
// filter out invalid libraryItemIds
|
||||||
@ -274,8 +305,9 @@ class CollectionController {
|
|||||||
* POST: /api/collections/:id/batch/remove
|
* POST: /api/collections/:id/batch/remove
|
||||||
* Remove multiple books from collection
|
* Remove multiple books from collection
|
||||||
* Req.body { books: <Array of library item ids> }
|
* Req.body { books: <Array of library item ids> }
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async removeBatch(req, res) {
|
async removeBatch(req, res) {
|
||||||
// filter out invalid libraryItemIds
|
// filter out invalid libraryItemIds
|
||||||
@ -325,6 +357,12 @@ class CollectionController {
|
|||||||
res.json(jsonExpanded)
|
res.json(jsonExpanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
*/
|
||||||
async middleware(req, res, next) {
|
async middleware(req, res, next) {
|
||||||
if (req.params.id) {
|
if (req.params.id) {
|
||||||
const collection = await Database.collectionModel.findByPk(req.params.id)
|
const collection = await Database.collectionModel.findByPk(req.params.id)
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
|
const { Request, Response, NextFunction } = require('express')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const SocketAuthority = require('../SocketAuthority')
|
const SocketAuthority = require('../SocketAuthority')
|
||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
|
|
||||||
const { validateUrl } = require('../utils/index')
|
const { validateUrl } = require('../utils/index')
|
||||||
|
|
||||||
//
|
/**
|
||||||
// This is a controller for routes that don't have a home yet :(
|
* @typedef RequestUserObject
|
||||||
//
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class CustomMetadataProviderController {
|
class CustomMetadataProviderController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET: /api/custom-metadata-providers
|
* GET: /api/custom-metadata-providers
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getAll(req, res) {
|
async getAll(req, res) {
|
||||||
const providers = await Database.customMetadataProviderModel.findAll()
|
const providers = await Database.customMetadataProviderModel.findAll()
|
||||||
@ -27,8 +32,8 @@ class CustomMetadataProviderController {
|
|||||||
/**
|
/**
|
||||||
* POST: /api/custom-metadata-providers
|
* POST: /api/custom-metadata-providers
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async create(req, res) {
|
async create(req, res) {
|
||||||
const { name, url, mediaType, authHeaderValue } = req.body
|
const { name, url, mediaType, authHeaderValue } = req.body
|
||||||
@ -61,8 +66,8 @@ class CustomMetadataProviderController {
|
|||||||
/**
|
/**
|
||||||
* DELETE: /api/custom-metadata-providers/:id
|
* DELETE: /api/custom-metadata-providers/:id
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
const slug = `custom-${req.params.id}`
|
const slug = `custom-${req.params.id}`
|
||||||
@ -96,9 +101,9 @@ class CustomMetadataProviderController {
|
|||||||
/**
|
/**
|
||||||
* Middleware that requires admin or up
|
* Middleware that requires admin or up
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
* @param {import('express').NextFunction} next
|
* @param {NextFunction} next
|
||||||
*/
|
*/
|
||||||
async middleware(req, res, next) {
|
async middleware(req, res, next) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
|
const { Request, Response, NextFunction } = require('express')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const SocketAuthority = require('../SocketAuthority')
|
const SocketAuthority = require('../SocketAuthority')
|
||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class EmailController {
|
class EmailController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET: /api/emails/settings
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
getSettings(req, res) {
|
getSettings(req, res) {
|
||||||
res.json({
|
res.json({
|
||||||
settings: Database.emailSettings
|
settings: Database.emailSettings
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PATCH: /api/emails/settings
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async updateSettings(req, res) {
|
async updateSettings(req, res) {
|
||||||
const updated = Database.emailSettings.update(req.body)
|
const updated = Database.emailSettings.update(req.body)
|
||||||
if (updated) {
|
if (updated) {
|
||||||
@ -21,10 +41,24 @@ class EmailController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: /api/emails/test
|
||||||
|
*
|
||||||
|
* @this {import('../routers/ApiRouter')}
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async sendTest(req, res) {
|
async sendTest(req, res) {
|
||||||
this.emailManager.sendTest(res)
|
this.emailManager.sendTest(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: /api/emails/ereader-devices
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async updateEReaderDevices(req, res) {
|
async updateEReaderDevices(req, res) {
|
||||||
if (!req.body.ereaderDevices || !Array.isArray(req.body.ereaderDevices)) {
|
if (!req.body.ereaderDevices || !Array.isArray(req.body.ereaderDevices)) {
|
||||||
return res.status(400).send('Invalid payload. ereaderDevices array required')
|
return res.status(400).send('Invalid payload. ereaderDevices array required')
|
||||||
@ -52,11 +86,12 @@ class EmailController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* POST: /api/emails/send-ebook-to-device
|
||||||
* Send ebook to device
|
* Send ebook to device
|
||||||
* User must have access to device and library item
|
* User must have access to device and library item
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async sendEBookToDevice(req, res) {
|
async sendEBookToDevice(req, res) {
|
||||||
Logger.debug(`[EmailController] Send ebook to device requested by user "${req.user.username}" for libraryItemId=${req.body.libraryItemId}, deviceName=${req.body.deviceName}`)
|
Logger.debug(`[EmailController] Send ebook to device requested by user "${req.user.username}" for libraryItemId=${req.body.libraryItemId}, deviceName=${req.body.deviceName}`)
|
||||||
@ -89,6 +124,12 @@ class EmailController {
|
|||||||
this.emailManager.sendEBookToDevice(ebookFile, device, res)
|
this.emailManager.sendEBookToDevice(ebookFile, device, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
*/
|
||||||
adminMiddleware(req, res, next) {
|
adminMiddleware(req, res, next) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
|
const { Request, Response } = require('express')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
const { toNumber } = require('../utils/index')
|
const { toNumber } = require('../utils/index')
|
||||||
const fileUtils = require('../utils/fileUtils')
|
const fileUtils = require('../utils/fileUtils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class FileSystemController {
|
class FileSystemController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getPaths(req, res) {
|
async getPaths(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
@ -67,7 +75,12 @@ class FileSystemController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: api/filesystem/pathexists
|
/**
|
||||||
|
* POST: /api/filesystem/pathexists
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async checkPathExists(req, res) {
|
async checkPathExists(req, res) {
|
||||||
if (!req.user.canUpload) {
|
if (!req.user.canUpload) {
|
||||||
Logger.error(`[FileSystemController] Non-admin user "${req.user.username}" attempting to check path exists`)
|
Logger.error(`[FileSystemController] Non-admin user "${req.user.username}" attempting to check path exists`)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const { Request, Response, NextFunction } = require('express')
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
@ -22,9 +23,23 @@ const libraryFilters = require('../utils/queries/libraryFilters')
|
|||||||
const libraryItemsPodcastFilters = require('../utils/queries/libraryItemsPodcastFilters')
|
const libraryItemsPodcastFilters = require('../utils/queries/libraryItemsPodcastFilters')
|
||||||
const authorFilters = require('../utils/queries/authorFilters')
|
const authorFilters = require('../utils/queries/authorFilters')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RequestUserObject
|
||||||
|
* @property {import('../models/User')} user
|
||||||
|
*
|
||||||
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
|
*/
|
||||||
|
|
||||||
class LibraryController {
|
class LibraryController {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: /api/libraries
|
||||||
|
* Create a new library
|
||||||
|
*
|
||||||
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
|
*/
|
||||||
async create(req, res) {
|
async create(req, res) {
|
||||||
const newLibraryPayload = {
|
const newLibraryPayload = {
|
||||||
...req.body
|
...req.body
|
||||||
@ -98,8 +113,8 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id
|
* GET: /api/libraries/:id
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async findOne(req, res) {
|
async findOne(req, res) {
|
||||||
const includeArray = (req.query.include || '').split(',')
|
const includeArray = (req.query.include || '').split(',')
|
||||||
@ -121,8 +136,8 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/episode-downloads
|
* GET: /api/libraries/:id/episode-downloads
|
||||||
* Get podcast episodes in download queue
|
* Get podcast episodes in download queue
|
||||||
* @param {*} req
|
* @param {RequestWithUser} req
|
||||||
* @param {*} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getEpisodeDownloadQueue(req, res) {
|
async getEpisodeDownloadQueue(req, res) {
|
||||||
const libraryDownloadQueueDetails = this.podcastManager.getDownloadQueueDetails(req.library.id)
|
const libraryDownloadQueueDetails = this.podcastManager.getDownloadQueueDetails(req.library.id)
|
||||||
@ -132,8 +147,8 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* PATCH: /api/libraries/:id
|
* PATCH: /api/libraries/:id
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async update(req, res) {
|
async update(req, res) {
|
||||||
/** @type {import('../objects/Library')} */
|
/** @type {import('../objects/Library')} */
|
||||||
@ -235,8 +250,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* DELETE: /api/libraries/:id
|
* DELETE: /api/libraries/:id
|
||||||
* Delete a library
|
* Delete a library
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
const library = req.library
|
const library = req.library
|
||||||
@ -298,8 +314,8 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET /api/libraries/:id/items
|
* GET /api/libraries/:id/items
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getLibraryItems(req, res) {
|
async getLibraryItems(req, res) {
|
||||||
const include = (req.query.include || '')
|
const include = (req.query.include || '')
|
||||||
@ -340,8 +356,8 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* DELETE: /libraries/:id/issues
|
* DELETE: /libraries/:id/issues
|
||||||
* Remove all library items missing or invalid
|
* Remove all library items missing or invalid
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async removeLibraryItemsWithIssues(req, res) {
|
async removeLibraryItemsWithIssues(req, res) {
|
||||||
const libraryItemsWithIssues = await Database.libraryItemModel.findAll({
|
const libraryItemsWithIssues = await Database.libraryItemModel.findAll({
|
||||||
@ -398,8 +414,8 @@ class LibraryController {
|
|||||||
* GET: /api/libraries/:id/series
|
* GET: /api/libraries/:id/series
|
||||||
* Optional query string: `?include=rssfeed` that adds `rssFeed` to series if a feed is open
|
* Optional query string: `?include=rssfeed` that adds `rssFeed` to series if a feed is open
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getAllSeriesForLibrary(req, res) {
|
async getAllSeriesForLibrary(req, res) {
|
||||||
const include = (req.query.include || '')
|
const include = (req.query.include || '')
|
||||||
@ -434,8 +450,8 @@ class LibraryController {
|
|||||||
* rssfeed: adds `rssFeed` to series object if a feed is open
|
* rssfeed: adds `rssFeed` to series object if a feed is open
|
||||||
* progress: adds `progress` to series object with { libraryItemIds:Array<llid>, libraryItemIdsFinished:Array<llid>, isFinished:boolean }
|
* progress: adds `progress` to series object with { libraryItemIds:Array<llid>, libraryItemIdsFinished:Array<llid>, isFinished:boolean }
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res - Series
|
* @param {Response} res - Series
|
||||||
*/
|
*/
|
||||||
async getSeriesForLibrary(req, res) {
|
async getSeriesForLibrary(req, res) {
|
||||||
const include = (req.query.include || '')
|
const include = (req.query.include || '')
|
||||||
@ -470,8 +486,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/collections
|
* GET: /api/libraries/:id/collections
|
||||||
* Get all collections for library
|
* Get all collections for library
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getCollectionsForLibrary(req, res) {
|
async getCollectionsForLibrary(req, res) {
|
||||||
const include = (req.query.include || '')
|
const include = (req.query.include || '')
|
||||||
@ -508,8 +525,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/playlists
|
* GET: /api/libraries/:id/playlists
|
||||||
* Get playlists for user in library
|
* Get playlists for user in library
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getUserPlaylistsForLibrary(req, res) {
|
async getUserPlaylistsForLibrary(req, res) {
|
||||||
let playlistsForUser = await Database.playlistModel.getOldPlaylistsForUserAndLibrary(req.user.id, req.library.id)
|
let playlistsForUser = await Database.playlistModel.getOldPlaylistsForUserAndLibrary(req.user.id, req.library.id)
|
||||||
@ -532,8 +550,9 @@ class LibraryController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/filterdata
|
* GET: /api/libraries/:id/filterdata
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getLibraryFilterData(req, res) {
|
async getLibraryFilterData(req, res) {
|
||||||
const filterData = await libraryFilters.getFilterData(req.library.mediaType, req.library.id)
|
const filterData = await libraryFilters.getFilterData(req.library.mediaType, req.library.id)
|
||||||
@ -543,8 +562,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/personalized
|
* GET: /api/libraries/:id/personalized
|
||||||
* Home page shelves
|
* Home page shelves
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getUserPersonalizedShelves(req, res) {
|
async getUserPersonalizedShelves(req, res) {
|
||||||
const limitPerShelf = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) || 10 : 10
|
const limitPerShelf = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) || 10 : 10
|
||||||
@ -559,8 +579,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* POST: /api/libraries/order
|
* POST: /api/libraries/order
|
||||||
* Change the display order of libraries
|
* Change the display order of libraries
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async reorder(req, res) {
|
async reorder(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
@ -598,9 +619,10 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/search
|
* GET: /api/libraries/:id/search
|
||||||
* Search library items with query
|
* Search library items with query
|
||||||
|
*
|
||||||
* ?q=search
|
* ?q=search
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async search(req, res) {
|
async search(req, res) {
|
||||||
if (!req.query.q || typeof req.query.q !== 'string') {
|
if (!req.query.q || typeof req.query.q !== 'string') {
|
||||||
@ -616,8 +638,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/stats
|
* GET: /api/libraries/:id/stats
|
||||||
* Get stats for library
|
* Get stats for library
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async stats(req, res) {
|
async stats(req, res) {
|
||||||
const stats = {
|
const stats = {
|
||||||
@ -658,8 +681,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/authors
|
* GET: /api/libraries/:id/authors
|
||||||
* Get authors for library
|
* Get authors for library
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getAuthors(req, res) {
|
async getAuthors(req, res) {
|
||||||
const { bookWhere, replacements } = libraryItemsBookFilters.getUserPermissionBookWhereQuery(req.user)
|
const { bookWhere, replacements } = libraryItemsBookFilters.getUserPermissionBookWhereQuery(req.user)
|
||||||
@ -696,8 +720,9 @@ class LibraryController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/narrators
|
* GET: /api/libraries/:id/narrators
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getNarrators(req, res) {
|
async getNarrators(req, res) {
|
||||||
// Get all books with narrators
|
// Get all books with narrators
|
||||||
@ -742,8 +767,9 @@ class LibraryController {
|
|||||||
* Update narrator name
|
* Update narrator name
|
||||||
* :narratorId is base64 encoded name
|
* :narratorId is base64 encoded name
|
||||||
* req.body { name }
|
* req.body { name }
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async updateNarrator(req, res) {
|
async updateNarrator(req, res) {
|
||||||
if (!req.user.canUpdate) {
|
if (!req.user.canUpdate) {
|
||||||
@ -792,8 +818,9 @@ class LibraryController {
|
|||||||
* DELETE: /api/libraries/:id/narrators/:narratorId
|
* DELETE: /api/libraries/:id/narrators/:narratorId
|
||||||
* Remove narrator
|
* Remove narrator
|
||||||
* :narratorId is base64 encoded name
|
* :narratorId is base64 encoded name
|
||||||
* @param {*} req
|
*
|
||||||
* @param {*} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async removeNarrator(req, res) {
|
async removeNarrator(req, res) {
|
||||||
if (!req.user.canUpdate) {
|
if (!req.user.canUpdate) {
|
||||||
@ -835,8 +862,8 @@ class LibraryController {
|
|||||||
* GET: /api/libraries/:id/matchall
|
* GET: /api/libraries/:id/matchall
|
||||||
* Quick match all library items. Book libraries only.
|
* Quick match all library items. Book libraries only.
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async matchAll(req, res) {
|
async matchAll(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
@ -852,8 +879,8 @@ class LibraryController {
|
|||||||
* Optional query:
|
* Optional query:
|
||||||
* ?force=1
|
* ?force=1
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async scan(req, res) {
|
async scan(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
@ -872,8 +899,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/recent-episodes
|
* GET: /api/libraries/:id/recent-episodes
|
||||||
* Used for latest page
|
* Used for latest page
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getRecentEpisodes(req, res) {
|
async getRecentEpisodes(req, res) {
|
||||||
if (!req.library.isPodcast) {
|
if (!req.library.isPodcast) {
|
||||||
@ -894,8 +922,9 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* GET: /api/libraries/:id/opml
|
* GET: /api/libraries/:id/opml
|
||||||
* Get OPML file for a podcast library
|
* Get OPML file for a podcast library
|
||||||
* @param {import('express').Request} req
|
*
|
||||||
* @param {import('express').Response} res
|
* @param {RequestWithUser} req
|
||||||
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getOPMLFile(req, res) {
|
async getOPMLFile(req, res) {
|
||||||
const userPermissionPodcastWhere = libraryItemsPodcastFilters.getUserPermissionPodcastWhereQuery(req.user)
|
const userPermissionPodcastWhere = libraryItemsPodcastFilters.getUserPermissionPodcastWhereQuery(req.user)
|
||||||
@ -920,8 +949,8 @@ class LibraryController {
|
|||||||
/**
|
/**
|
||||||
* Remove all metadata.json or metadata.abs files in library item folders
|
* Remove all metadata.json or metadata.abs files in library item folders
|
||||||
*
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async removeAllMetadataFiles(req, res) {
|
async removeAllMetadataFiles(req, res) {
|
||||||
if (!req.user.isAdminOrUp) {
|
if (!req.user.isAdminOrUp) {
|
||||||
@ -968,10 +997,10 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Middleware that is not using libraryItems from memory
|
*
|
||||||
* @param {import('express').Request} req
|
* @param {RequestWithUser} req
|
||||||
* @param {import('express').Response} res
|
* @param {Response} res
|
||||||
* @param {import('express').NextFunction} next
|
* @param {NextFunction} next
|
||||||
*/
|
*/
|
||||||
async middleware(req, res, next) {
|
async middleware(req, res, next) {
|
||||||
if (!req.user.checkCanAccessLibrary(req.params.id)) {
|
if (!req.user.checkCanAccessLibrary(req.params.id)) {
|
||||||
|
@ -17,10 +17,10 @@ const CoverManager = require('../managers/CoverManager')
|
|||||||
const ShareManager = require('../managers/ShareManager')
|
const ShareManager = require('../managers/ShareManager')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class LibraryItemController {
|
class LibraryItemController {
|
||||||
|
@ -7,10 +7,10 @@ const { toNumber, isNullOrNaN } = require('../utils/index')
|
|||||||
const userStats = require('../utils/queries/userStats')
|
const userStats = require('../utils/queries/userStats')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MeController {
|
class MeController {
|
||||||
|
@ -15,10 +15,10 @@ const TaskManager = require('../managers/TaskManager')
|
|||||||
const adminStats = require('../utils/queries/adminStats')
|
const adminStats = require('../utils/queries/adminStats')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MiscController {
|
class MiscController {
|
||||||
|
@ -3,10 +3,10 @@ const Database = require('../Database')
|
|||||||
const { version } = require('../../package.json')
|
const { version } = require('../../package.json')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class NotificationController {
|
class NotificationController {
|
||||||
|
@ -6,10 +6,10 @@ const Database = require('../Database')
|
|||||||
const Playlist = require('../objects/Playlist')
|
const Playlist = require('../objects/Playlist')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PlaylistController {
|
class PlaylistController {
|
||||||
|
@ -15,10 +15,10 @@ const CoverManager = require('../managers/CoverManager')
|
|||||||
const LibraryItem = require('../objects/LibraryItem')
|
const LibraryItem = require('../objects/LibraryItem')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PodcastController {
|
class PodcastController {
|
||||||
@ -129,7 +129,7 @@ class PodcastController {
|
|||||||
* @typedef getPodcastFeedReqBody
|
* @typedef getPodcastFeedReqBody
|
||||||
* @property {string} rssFeed
|
* @property {string} rssFeed
|
||||||
*
|
*
|
||||||
* @param {Request<{}, {}, getPodcastFeedReqBody, {}> & RequestUserObjects} req
|
* @param {Request<{}, {}, getPodcastFeedReqBody, {}> & RequestUserObject} req
|
||||||
* @param {Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async getPodcastFeed(req, res) {
|
async getPodcastFeed(req, res) {
|
||||||
|
@ -4,10 +4,10 @@ const Database = require('../Database')
|
|||||||
const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters')
|
const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class RSSFeedController {
|
class RSSFeedController {
|
||||||
|
@ -8,10 +8,10 @@ const Database = require('../Database')
|
|||||||
const { isValidASIN } = require('../utils')
|
const { isValidASIN } = require('../utils')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SearchController {
|
class SearchController {
|
||||||
|
@ -5,10 +5,10 @@ const Database = require('../Database')
|
|||||||
const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters')
|
const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SeriesController {
|
class SeriesController {
|
||||||
|
@ -6,10 +6,10 @@ const { toNumber, isUUID } = require('../utils/index')
|
|||||||
const ShareManager = require('../managers/ShareManager')
|
const ShareManager = require('../managers/ShareManager')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SessionController {
|
class SessionController {
|
||||||
@ -206,7 +206,7 @@ class SessionController {
|
|||||||
* @typedef batchDeleteReqBody
|
* @typedef batchDeleteReqBody
|
||||||
* @property {string[]} sessions
|
* @property {string[]} sessions
|
||||||
*
|
*
|
||||||
* @param {Request<{}, {}, batchDeleteReqBody, {}> & RequestUserObjects} req
|
* @param {Request<{}, {}, batchDeleteReqBody, {}> & RequestUserObject} req
|
||||||
* @param {Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async batchDelete(req, res) {
|
async batchDelete(req, res) {
|
||||||
|
@ -12,10 +12,10 @@ const PlaybackSession = require('../objects/PlaybackSession')
|
|||||||
const ShareManager = require('../managers/ShareManager')
|
const ShareManager = require('../managers/ShareManager')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ShareController {
|
class ShareController {
|
||||||
|
@ -3,10 +3,10 @@ const Logger = require('../Logger')
|
|||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ToolsController {
|
class ToolsController {
|
||||||
|
@ -9,16 +9,15 @@ const User = require('../objects/user/User')
|
|||||||
const { toNumber } = require('../utils/index')
|
const { toNumber } = require('../utils/index')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef RequestUserObjects
|
* @typedef RequestUserObject
|
||||||
* @property {import('../models/User')} user
|
* @property {import('../models/User')} user
|
||||||
*
|
*
|
||||||
* @typedef {Request & RequestUserObjects} RequestWithUser
|
* @typedef {Request & RequestUserObject} RequestWithUser
|
||||||
*
|
*
|
||||||
* @typedef UserControllerRequestProps
|
* @typedef RequestEntityObject
|
||||||
* @property {import('../models/User')} user - User that made the request
|
* @property {import('../models/User')} reqUser
|
||||||
* @property {import('../objects/user/User')} [reqUser] - User for req param id
|
|
||||||
*
|
*
|
||||||
* @typedef {Request & UserControllerRequestProps} UserControllerRequest
|
* @typedef {RequestWithUser & RequestEntityObject} UserControllerRequest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class UserController {
|
class UserController {
|
||||||
@ -26,7 +25,7 @@ class UserController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {UserControllerRequest} req
|
* @param {RequestWithUser} req
|
||||||
* @param {Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
async findAll(req, res) {
|
async findAll(req, res) {
|
||||||
@ -100,7 +99,7 @@ class UserController {
|
|||||||
return oldMediaProgress
|
return oldMediaProgress
|
||||||
})
|
})
|
||||||
|
|
||||||
const userJson = req.reqUser.toJSONForBrowser(!req.user.isRoot)
|
const userJson = req.reqUser.toOldJSONForBrowser(!req.user.isRoot)
|
||||||
|
|
||||||
userJson.mediaProgress = oldMediaProgresses
|
userJson.mediaProgress = oldMediaProgresses
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ class UserController {
|
|||||||
|
|
||||||
const usernameExists = await Database.userModel.checkUserExistsWithUsername(username)
|
const usernameExists = await Database.userModel.checkUserExistsWithUsername(username)
|
||||||
if (usernameExists) {
|
if (usernameExists) {
|
||||||
return res.status(500).send('Username already taken')
|
return res.status(400).send('Username already taken')
|
||||||
}
|
}
|
||||||
|
|
||||||
account.id = uuidv4()
|
account.id = uuidv4()
|
||||||
@ -132,6 +131,7 @@ class UserController {
|
|||||||
account.createdAt = Date.now()
|
account.createdAt = Date.now()
|
||||||
const newUser = new User(account)
|
const newUser = new User(account)
|
||||||
|
|
||||||
|
// TODO: Create with new User model
|
||||||
const success = await Database.createUser(newUser)
|
const success = await Database.createUser(newUser)
|
||||||
if (success) {
|
if (success) {
|
||||||
SocketAuthority.adminEmitter('user_added', newUser.toJSONForBrowser())
|
SocketAuthority.adminEmitter('user_added', newUser.toJSONForBrowser())
|
||||||
@ -147,6 +147,8 @@ class UserController {
|
|||||||
* PATCH: /api/users/:id
|
* PATCH: /api/users/:id
|
||||||
* Update user
|
* Update user
|
||||||
*
|
*
|
||||||
|
* @this {import('../routers/ApiRouter')}
|
||||||
|
*
|
||||||
* @param {UserControllerRequest} req
|
* @param {UserControllerRequest} req
|
||||||
* @param {Response} res
|
* @param {Response} res
|
||||||
*/
|
*/
|
||||||
@ -158,12 +160,12 @@ class UserController {
|
|||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
var account = req.body
|
const updatePayload = req.body
|
||||||
var shouldUpdateToken = false
|
let shouldUpdateToken = false
|
||||||
|
|
||||||
// When changing username create a new API token
|
// When changing username create a new API token
|
||||||
if (account.username !== undefined && account.username !== user.username) {
|
if (updatePayload.username !== undefined && updatePayload.username !== user.username) {
|
||||||
const usernameExists = await Database.userModel.checkUserExistsWithUsername(account.username)
|
const usernameExists = await Database.userModel.checkUserExistsWithUsername(updatePayload.username)
|
||||||
if (usernameExists) {
|
if (usernameExists) {
|
||||||
return res.status(500).send('Username already taken')
|
return res.status(500).send('Username already taken')
|
||||||
}
|
}
|
||||||
@ -171,23 +173,25 @@ class UserController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Updating password
|
// Updating password
|
||||||
if (account.password) {
|
if (updatePayload.password) {
|
||||||
account.pash = await this.auth.hashPass(account.password)
|
updatePayload.pash = await this.auth.hashPass(updatePayload.password)
|
||||||
delete account.password
|
delete updatePayload.password
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.update(account)) {
|
// TODO: Update with new User model
|
||||||
|
const oldUser = Database.userModel.getOldUser(user)
|
||||||
|
if (oldUser.update(updatePayload)) {
|
||||||
if (shouldUpdateToken) {
|
if (shouldUpdateToken) {
|
||||||
user.token = await this.auth.generateAccessToken(user)
|
oldUser.token = await this.auth.generateAccessToken(oldUser)
|
||||||
Logger.info(`[UserController] User ${user.username} was generated a new api token`)
|
Logger.info(`[UserController] User ${oldUser.username} has generated a new api token`)
|
||||||
}
|
}
|
||||||
await Database.updateUser(user)
|
await Database.updateUser(oldUser)
|
||||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', user.toJSONForBrowser())
|
SocketAuthority.clientEmitter(req.user.id, 'user_updated', oldUser.toJSONForBrowser())
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
user: user.toJSONForBrowser()
|
user: oldUser.toJSONForBrowser()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +225,8 @@ class UserController {
|
|||||||
await playlist.destroy()
|
await playlist.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
const userJson = user.toJSONForBrowser()
|
const userJson = user.toOldJSONForBrowser()
|
||||||
await Database.removeUser(user.id)
|
await user.destroy()
|
||||||
SocketAuthority.adminEmitter('user_removed', userJson)
|
SocketAuthority.adminEmitter('user_removed', userJson)
|
||||||
res.json({
|
res.json({
|
||||||
success: true
|
success: true
|
||||||
@ -237,13 +241,16 @@ class UserController {
|
|||||||
*/
|
*/
|
||||||
async unlinkFromOpenID(req, res) {
|
async unlinkFromOpenID(req, res) {
|
||||||
Logger.debug(`[UserController] Unlinking user "${req.reqUser.username}" from OpenID with sub "${req.reqUser.authOpenIDSub}"`)
|
Logger.debug(`[UserController] Unlinking user "${req.reqUser.username}" from OpenID with sub "${req.reqUser.authOpenIDSub}"`)
|
||||||
req.reqUser.authOpenIDSub = null
|
|
||||||
if (await Database.userModel.updateFromOld(req.reqUser)) {
|
if (!req.reqUser.authOpenIDSub) {
|
||||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.reqUser.toJSONForBrowser())
|
return res.sendStatus(200)
|
||||||
res.sendStatus(200)
|
|
||||||
} else {
|
|
||||||
res.sendStatus(500)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.reqUser.extraData.authOpenIDSub = null
|
||||||
|
req.reqUser.changed('extraData', true)
|
||||||
|
await req.reqUser.save()
|
||||||
|
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.reqUser.toOldJSONForBrowser())
|
||||||
|
res.sendStatus(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,8 +325,7 @@ class UserController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req.params.id) {
|
if (req.params.id) {
|
||||||
// TODO: Update to use new user model
|
req.reqUser = await Database.userModel.getUserById(req.params.id)
|
||||||
req.reqUser = await Database.userModel.getOldUserById(req.params.id)
|
|
||||||
if (!req.reqUser) {
|
if (!req.reqUser) {
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
}
|
}
|
||||||
|
@ -217,14 +217,6 @@ class User extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static removeById(userId) {
|
|
||||||
return this.destroy({
|
|
||||||
where: {
|
|
||||||
id: userId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create root user
|
* Create root user
|
||||||
* @param {string} username
|
* @param {string} username
|
||||||
|
@ -56,6 +56,7 @@ class ApiRouter {
|
|||||||
this.cronManager = Server.cronManager
|
this.cronManager = Server.cronManager
|
||||||
/** @type {import('../managers/NotificationManager')} */
|
/** @type {import('../managers/NotificationManager')} */
|
||||||
this.notificationManager = Server.notificationManager
|
this.notificationManager = Server.notificationManager
|
||||||
|
/** @type {import('../managers/EmailManager')} */
|
||||||
this.emailManager = Server.emailManager
|
this.emailManager = Server.emailManager
|
||||||
this.apiCacheManager = Server.apiCacheManager
|
this.apiCacheManager = Server.apiCacheManager
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user