mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-03 01:35:08 +02:00
Merge pull request #2769 from Sapd/openid-permissions
OpenID: Integrate permissions (Fixes #2523)
This commit is contained in:
commit
a9c9c447f1
29 changed files with 422 additions and 61 deletions
|
@ -1,6 +1,7 @@
|
|||
const packageJson = require('../../../package.json')
|
||||
const { BookshelfView } = require('../../utils/constants')
|
||||
const Logger = require('../../Logger')
|
||||
const User = require('../user/User')
|
||||
|
||||
class ServerSettings {
|
||||
constructor(settings) {
|
||||
|
@ -72,6 +73,8 @@ class ServerSettings {
|
|||
this.authOpenIDAutoRegister = false
|
||||
this.authOpenIDMatchExistingBy = null
|
||||
this.authOpenIDMobileRedirectURIs = ['audiobookshelf://oauth']
|
||||
this.authOpenIDGroupClaim = ''
|
||||
this.authOpenIDAdvancedPermsClaim = ''
|
||||
|
||||
if (settings) {
|
||||
this.construct(settings)
|
||||
|
@ -129,6 +132,8 @@ class ServerSettings {
|
|||
this.authOpenIDAutoRegister = !!settings.authOpenIDAutoRegister
|
||||
this.authOpenIDMatchExistingBy = settings.authOpenIDMatchExistingBy || null
|
||||
this.authOpenIDMobileRedirectURIs = settings.authOpenIDMobileRedirectURIs || ['audiobookshelf://oauth']
|
||||
this.authOpenIDGroupClaim = settings.authOpenIDGroupClaim || ''
|
||||
this.authOpenIDAdvancedPermsClaim = settings.authOpenIDAdvancedPermsClaim || ''
|
||||
|
||||
if (!Array.isArray(this.authActiveAuthMethods)) {
|
||||
this.authActiveAuthMethods = ['local']
|
||||
|
@ -216,7 +221,9 @@ class ServerSettings {
|
|||
authOpenIDAutoLaunch: this.authOpenIDAutoLaunch,
|
||||
authOpenIDAutoRegister: this.authOpenIDAutoRegister,
|
||||
authOpenIDMatchExistingBy: this.authOpenIDMatchExistingBy,
|
||||
authOpenIDMobileRedirectURIs: this.authOpenIDMobileRedirectURIs // Do not return to client
|
||||
authOpenIDMobileRedirectURIs: this.authOpenIDMobileRedirectURIs, // Do not return to client
|
||||
authOpenIDGroupClaim: this.authOpenIDGroupClaim, // Do not return to client
|
||||
authOpenIDAdvancedPermsClaim: this.authOpenIDAdvancedPermsClaim // Do not return to client
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,6 +233,8 @@ class ServerSettings {
|
|||
delete json.authOpenIDClientID
|
||||
delete json.authOpenIDClientSecret
|
||||
delete json.authOpenIDMobileRedirectURIs
|
||||
delete json.authOpenIDGroupClaim
|
||||
delete json.authOpenIDAdvancedPermsClaim
|
||||
return json
|
||||
}
|
||||
|
||||
|
@ -262,7 +271,11 @@ class ServerSettings {
|
|||
authOpenIDAutoLaunch: this.authOpenIDAutoLaunch,
|
||||
authOpenIDAutoRegister: this.authOpenIDAutoRegister,
|
||||
authOpenIDMatchExistingBy: this.authOpenIDMatchExistingBy,
|
||||
authOpenIDMobileRedirectURIs: this.authOpenIDMobileRedirectURIs // Do not return to client
|
||||
authOpenIDMobileRedirectURIs: this.authOpenIDMobileRedirectURIs, // Do not return to client
|
||||
authOpenIDGroupClaim: this.authOpenIDGroupClaim, // Do not return to client
|
||||
authOpenIDAdvancedPermsClaim: this.authOpenIDAdvancedPermsClaim, // Do not return to client
|
||||
|
||||
authOpenIDSamplePermissions: User.getSampleAbsPermissions()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,111 @@ class User {
|
|||
return hasUpdates
|
||||
}
|
||||
|
||||
// List of expected permission properties from the client
|
||||
static permissionMapping = {
|
||||
canDownload: 'download',
|
||||
canUpload: 'upload',
|
||||
canDelete: 'delete',
|
||||
canUpdate: 'update',
|
||||
canAccessExplicitContent: 'accessExplicitContent',
|
||||
canAccessAllLibraries: 'accessAllLibraries',
|
||||
canAccessAllTags: 'accessAllTags',
|
||||
tagsAreDenylist: 'selectedTagsNotAccessible',
|
||||
// Direct mapping for array-based permissions
|
||||
allowedLibraries: 'librariesAccessible',
|
||||
allowedTags: 'itemTagsSelected'
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user permissions from external JSON
|
||||
*
|
||||
* @param {Object} absPermissions JSON containing user permissions
|
||||
* @returns {boolean} true if updates were made
|
||||
*/
|
||||
updatePermissionsFromExternalJSON(absPermissions) {
|
||||
let hasUpdates = false
|
||||
let updatedUserPermissions = {}
|
||||
|
||||
// Initialize all permissions to false first
|
||||
Object.keys(User.permissionMapping).forEach(mappingKey => {
|
||||
const userPermKey = User.permissionMapping[mappingKey]
|
||||
if (typeof this.permissions[userPermKey] === 'boolean') {
|
||||
updatedUserPermissions[userPermKey] = false // Default to false for boolean permissions
|
||||
}
|
||||
})
|
||||
|
||||
// Map the boolean permissions from absPermissions
|
||||
Object.keys(absPermissions).forEach(absKey => {
|
||||
const userPermKey = User.permissionMapping[absKey]
|
||||
if (!userPermKey) {
|
||||
throw new Error(`Unexpected permission property: ${absKey}`)
|
||||
}
|
||||
|
||||
if (updatedUserPermissions[userPermKey] !== undefined) {
|
||||
updatedUserPermissions[userPermKey] = !!absPermissions[absKey]
|
||||
}
|
||||
})
|
||||
|
||||
// Update user permissions if changes were made
|
||||
if (JSON.stringify(this.permissions) !== JSON.stringify(updatedUserPermissions)) {
|
||||
this.permissions = updatedUserPermissions
|
||||
hasUpdates = true
|
||||
}
|
||||
|
||||
// Handle allowedLibraries
|
||||
if (this.permissions.accessAllLibraries) {
|
||||
if (this.librariesAccessible.length) {
|
||||
this.librariesAccessible = []
|
||||
hasUpdates = true
|
||||
}
|
||||
} else if (absPermissions.allowedLibraries?.length && absPermissions.allowedLibraries.join(',') !== this.librariesAccessible.join(',')) {
|
||||
if (absPermissions.allowedLibraries.some(lid => typeof lid !== 'string')) {
|
||||
throw new Error('Invalid permission property "allowedLibraries", expecting array of strings')
|
||||
}
|
||||
this.librariesAccessible = absPermissions.allowedLibraries
|
||||
hasUpdates = true
|
||||
}
|
||||
|
||||
// Handle allowedTags
|
||||
if (this.permissions.accessAllTags) {
|
||||
if (this.itemTagsSelected.length) {
|
||||
this.itemTagsSelected = []
|
||||
hasUpdates = true
|
||||
}
|
||||
} else if (absPermissions.allowedTags?.length && absPermissions.allowedTags.join(',') !== this.itemTagsSelected.join(',')) {
|
||||
if (absPermissions.allowedTags.some(tag => typeof tag !== 'string')) {
|
||||
throw new Error('Invalid permission property "allowedTags", expecting array of strings')
|
||||
}
|
||||
this.itemTagsSelected = absPermissions.allowedTags
|
||||
hasUpdates = true
|
||||
}
|
||||
|
||||
return hasUpdates
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a sample to show how a JSON for updatePermissionsFromExternalJSON should look like
|
||||
*
|
||||
* @returns {string} JSON string
|
||||
*/
|
||||
static getSampleAbsPermissions() {
|
||||
// Start with a template object where all permissions are false for simplicity
|
||||
const samplePermissions = Object.keys(User.permissionMapping).reduce((acc, key) => {
|
||||
// For array-based permissions, provide a sample array
|
||||
if (key === 'allowedLibraries') {
|
||||
acc[key] = [`5406ba8a-16e1-451d-96d7-4931b0a0d966`, `918fd848-7c1d-4a02-818a-847435a879ca`]
|
||||
} else if (key === 'allowedTags') {
|
||||
acc[key] = [`ExampleTag`, `AnotherTag`, `ThirdTag`]
|
||||
} else {
|
||||
acc[key] = false
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
return JSON.stringify(samplePermissions, null, 2) // Pretty print the JSON
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first available library id for user
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue