mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-13 06:51:29 +00:00
Merge 464b720d9e into 47ea6b5092
This commit is contained in:
commit
3de0dedfd9
11 changed files with 236 additions and 1 deletions
101
test/server/controllers/LibraryItemController.canStream.test.js
Normal file
101
test/server/controllers/LibraryItemController.canStream.test.js
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const LibraryItemController = require('../../../server/controllers/LibraryItemController')
|
||||
const Logger = require('../../../server/Logger')
|
||||
|
||||
describe('LibraryItemController - canStream enforcement', () => {
|
||||
beforeEach(() => {
|
||||
sinon.stub(Logger, 'warn')
|
||||
sinon.stub(Logger, 'error')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
describe('startPlaybackSession', () => {
|
||||
it('should return 403 when user cannot stream', () => {
|
||||
const req = {
|
||||
user: { canStream: false, username: 'testuser' },
|
||||
libraryItem: { hasAudioTracks: true, id: 'li_test' }
|
||||
}
|
||||
const res = { sendStatus: sinon.spy() }
|
||||
|
||||
LibraryItemController.startPlaybackSession.call({}, req, res)
|
||||
|
||||
expect(res.sendStatus.calledWith(403)).to.be.true
|
||||
expect(Logger.warn.calledOnce).to.be.true
|
||||
expect(Logger.warn.firstCall.args[0]).to.include('testuser')
|
||||
})
|
||||
|
||||
it('should not block when user can stream', () => {
|
||||
const startSessionRequest = sinon.spy()
|
||||
const req = {
|
||||
user: { canStream: true },
|
||||
libraryItem: { hasAudioTracks: true, id: 'li_test' }
|
||||
}
|
||||
const res = { sendStatus: sinon.spy() }
|
||||
|
||||
LibraryItemController.startPlaybackSession.call(
|
||||
{ playbackSessionManager: { startSessionRequest } },
|
||||
req,
|
||||
res
|
||||
)
|
||||
|
||||
expect(res.sendStatus.called).to.be.false
|
||||
expect(startSessionRequest.calledOnce).to.be.true
|
||||
})
|
||||
|
||||
it('should return 404 when item has no audio tracks', () => {
|
||||
const req = {
|
||||
user: { canStream: true },
|
||||
libraryItem: { hasAudioTracks: false, id: 'li_test' }
|
||||
}
|
||||
const res = { sendStatus: sinon.spy() }
|
||||
|
||||
LibraryItemController.startPlaybackSession.call({}, req, res)
|
||||
|
||||
expect(res.sendStatus.calledWith(404)).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
describe('startEpisodePlaybackSession', () => {
|
||||
it('should return 403 when user cannot stream', () => {
|
||||
const req = {
|
||||
user: { canStream: false, username: 'testuser' },
|
||||
libraryItem: { isPodcast: true, id: 'li_test' },
|
||||
params: { episodeId: 'ep_1' }
|
||||
}
|
||||
const res = { sendStatus: sinon.spy() }
|
||||
|
||||
LibraryItemController.startEpisodePlaybackSession.call({}, req, res)
|
||||
|
||||
expect(res.sendStatus.calledWith(403)).to.be.true
|
||||
expect(Logger.warn.calledOnce).to.be.true
|
||||
})
|
||||
|
||||
it('should not block when user can stream', () => {
|
||||
const startSessionRequest = sinon.spy()
|
||||
const req = {
|
||||
user: { canStream: true },
|
||||
libraryItem: {
|
||||
isPodcast: true,
|
||||
id: 'li_test',
|
||||
media: { podcastEpisodes: [{ id: 'ep_1' }] }
|
||||
},
|
||||
params: { episodeId: 'ep_1' }
|
||||
}
|
||||
const res = { sendStatus: sinon.spy() }
|
||||
|
||||
LibraryItemController.startEpisodePlaybackSession.call(
|
||||
{ playbackSessionManager: { startSessionRequest } },
|
||||
req,
|
||||
res
|
||||
)
|
||||
|
||||
expect(res.sendStatus.called).to.be.false
|
||||
expect(startSessionRequest.calledOnce).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
78
test/server/models/User.canStream.test.js
Normal file
78
test/server/models/User.canStream.test.js
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
const { expect } = require('chai')
|
||||
const { Sequelize } = require('sequelize')
|
||||
|
||||
const Database = require('../../../server/Database')
|
||||
|
||||
describe('User - canStream permission', () => {
|
||||
beforeEach(async () => {
|
||||
global.ServerSettings = {}
|
||||
Database.sequelize = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
|
||||
Database.sequelize.uppercaseFirst = (str) => (str ? `${str[0].toUpperCase()}${str.substr(1)}` : '')
|
||||
await Database.buildModels()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await Database.sequelize.sync({ force: true })
|
||||
})
|
||||
|
||||
describe('getDefaultPermissionsForUserType', () => {
|
||||
it('should default stream to true for all user types', () => {
|
||||
for (const type of ['root', 'admin', 'user', 'guest']) {
|
||||
const permissions = Database.userModel.getDefaultPermissionsForUserType(type)
|
||||
expect(permissions.stream).to.equal(true, `stream should default to true for type "${type}"`)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('canStream getter', () => {
|
||||
it('should return true when stream permission is true and user is active', async () => {
|
||||
const user = await Database.userModel.create({
|
||||
username: 'testuser',
|
||||
pash: 'hashed',
|
||||
type: 'user',
|
||||
isActive: true,
|
||||
permissions: { stream: true, download: true }
|
||||
})
|
||||
expect(user.canStream).to.be.true
|
||||
})
|
||||
|
||||
it('should return false when stream permission is explicitly false', async () => {
|
||||
const user = await Database.userModel.create({
|
||||
username: 'testuser',
|
||||
pash: 'hashed',
|
||||
type: 'user',
|
||||
isActive: true,
|
||||
permissions: { stream: false, download: true }
|
||||
})
|
||||
expect(user.canStream).to.be.false
|
||||
})
|
||||
|
||||
it('should return true when stream permission is missing (migration safety)', async () => {
|
||||
const user = await Database.userModel.create({
|
||||
username: 'testuser',
|
||||
pash: 'hashed',
|
||||
type: 'user',
|
||||
isActive: true,
|
||||
permissions: { download: true }
|
||||
})
|
||||
expect(user.canStream).to.be.true
|
||||
})
|
||||
|
||||
it('should return false when user is inactive even with stream permission', async () => {
|
||||
const user = await Database.userModel.create({
|
||||
username: 'testuser',
|
||||
pash: 'hashed',
|
||||
type: 'user',
|
||||
isActive: false,
|
||||
permissions: { stream: true }
|
||||
})
|
||||
expect(user.canStream).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
describe('permissionMapping', () => {
|
||||
it('should map canStream to stream', () => {
|
||||
expect(Database.userModel.permissionMapping.canStream).to.equal('stream')
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue