mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-14 13:47:16 +02:00
adjusted SSOSettings model and changed all code based on the model
This commit is contained in:
parent
b12a38d12b
commit
3cd09eecba
@ -112,6 +112,9 @@ export default {
|
||||
if (payload.serverSettings) {
|
||||
this.$store.commit('setServerSettings', payload.serverSettings)
|
||||
}
|
||||
if (payload.SSOSettings) {
|
||||
this.$store.commit('sso/setSSOSettings', payload.SSOSettings)
|
||||
}
|
||||
|
||||
// Start scans currently running
|
||||
if (payload.librariesScanning) {
|
||||
|
@ -9,32 +9,32 @@
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<p class="pl-4 text-lg">Issuer </p>
|
||||
<ui-text-input v-model="oidc.issuer" :disabled="updatingSSOSettings" @input="updateSSOIssuer" />
|
||||
<ui-text-input v-model="issuer" :disabled="updatingSSOSettings" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<p class="pl-4 text-lg">Authorization URL </p>
|
||||
<ui-text-input v-model="oidc.authorizationURL" :disabled="updatingSSOSettings" @input="updateAuthorizationURL" />
|
||||
<ui-text-input v-model="authorizationURL" :disabled="updatingSSOSettings" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<p class="pl-4 text-lg">Token URL </p>
|
||||
<ui-text-input v-model="oidc.tokenURL" :disabled="updatingSSOSettings" @input="updateTokenURL" />
|
||||
<ui-text-input v-model="tokenURL" :disabled="updatingSSOSettings" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<p class="pl-4 text-lg">User Info URL </p>
|
||||
<ui-text-input v-model="oidc.userInfoURL" :disabled="updatingSSOSettings" @input="updateUserInfoURL" />
|
||||
<ui-text-input v-model="userInfoURL" :disabled="updatingSSOSettings" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<p class="pl-4 text-lg">Client ID </p>
|
||||
<ui-text-input v-model="oidc.clientID" :disabled="updatingSSOSettings" @input="updateClientID" />
|
||||
<ui-text-input v-model="clientID" :disabled="updatingSSOSettings" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<p class="pl-4 text-lg">Client Secret </p>
|
||||
<ui-text-input type="password" v-model="oidc.clientSecret" :disabled="updatingSSOSettings" @input="updateClientSecret" />
|
||||
<ui-text-input type="password" v-model="clientSecret" :disabled="updatingSSOSettings" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
@ -42,32 +42,32 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
<ui-toggle-switch v-model="permissions.createNewUser" :disabled="updatingSSOSettings" @input="updatePermissionCreateNewUser" />
|
||||
<ui-toggle-switch v-model="createNewUser" :disabled="updatingSSOSettings" />
|
||||
<p class="pl-4 text-lg">Create a new user on first login</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
<ui-toggle-switch v-model="permissions.download" :disabled="updatingSSOSettings || !permissions.createNewUser" @input="updatePermissionDownload" />
|
||||
<ui-toggle-switch v-model="permissionDownload" :disabled="updatingSSOSettings || !createNewUser" />
|
||||
<p class="pl-4 text-lg">The new user is allowed to download</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
<ui-toggle-switch v-model="permissions.update" :disabled="updatingSSOSettings || !permissions.createNewUser" @input="updatePermissionUpdate" />
|
||||
<ui-toggle-switch v-model="permissionUpdate" :disabled="updatingSSOSettings || !createNewUser" />
|
||||
<p class="pl-4 text-lg">The new user is allowed to update</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
<ui-toggle-switch v-model="permissions.delete" :disabled="updatingSSOSettings || !permissions.createNewUser" @input="updatePermissionDelete" />
|
||||
<ui-toggle-switch v-model="permissionDelete" :disabled="updatingSSOSettings || !createNewUser" />
|
||||
<p class="pl-4 text-lg">The new user is allowed to delete</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
<ui-toggle-switch v-model="permissions.upload" :disabled="updatingSSOSettings || !permissions.createNewUser" @input="updatePermissionUpload" />
|
||||
<ui-toggle-switch v-model="permissionUpload" :disabled="updatingSSOSettings || !createNewUser" />
|
||||
<p class="pl-4 text-lg">The new user is allowed to upload</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2">
|
||||
<ui-toggle-switch v-model="permissions.accessAllLibraries" :disabled="updatingSSOSettings || !permissions.createNewUser" @input="updatePermissionAccessAllLibraries" />
|
||||
<ui-toggle-switch v-model="permissionAccessAllLibraries" :disabled="updatingSSOSettings || !createNewUser" />
|
||||
<p class="pl-4 text-lg">The new user is allowed to access all libraries</p>
|
||||
</div>
|
||||
|
||||
@ -90,16 +90,28 @@ export default {
|
||||
clientID: "",
|
||||
clientSecret: "",
|
||||
},
|
||||
|
||||
permissions: {
|
||||
user: {
|
||||
createNewUser: false,
|
||||
download: false,
|
||||
update: false,
|
||||
delete: false,
|
||||
upload: false,
|
||||
accessAllLibraries: false
|
||||
isActive: true,
|
||||
settings: {
|
||||
mobileOrderBy: 'recent',
|
||||
mobileOrderDesc: true,
|
||||
mobileFilterBy: 'all',
|
||||
orderBy: 'book.title',
|
||||
orderDesc: false,
|
||||
filterBy: 'all',
|
||||
playbackRate: 1,
|
||||
bookshelfCoverSize: 120,
|
||||
collapseSeries: false
|
||||
},
|
||||
permissions: {
|
||||
download: false,
|
||||
update: false,
|
||||
delete: false,
|
||||
upload: false,
|
||||
accessAllLibraries: false
|
||||
}
|
||||
},
|
||||
|
||||
updatingSSOSettings: false,
|
||||
newSSOSettings: {}
|
||||
}
|
||||
@ -114,55 +126,136 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
SSOSettings() {
|
||||
return this.$store.state.SSOSettings
|
||||
return this.$store.state.sso
|
||||
},
|
||||
|
||||
issuer: {
|
||||
get() {
|
||||
return this.oidc.issuer
|
||||
return this.$store.state.sso.oidc.issuer
|
||||
},
|
||||
set(val) {
|
||||
this.oidc.issuer = val
|
||||
// this.$store.state.sso.oidc.issuer = val
|
||||
}
|
||||
},
|
||||
authorizationURL: {
|
||||
get() {
|
||||
return this.oidc.authorizationURL
|
||||
return this.$store.state.sso.oidc.authorizationURL
|
||||
},
|
||||
set(val) {
|
||||
this.oidc.authorizationURL = val
|
||||
// this.$store.state.sso.oidc.authorizationURL = val
|
||||
}
|
||||
},
|
||||
tokenURL: {
|
||||
get() {
|
||||
return this.oidc.tokenURL
|
||||
return this.$store.state.sso.oidc.tokenURL
|
||||
},
|
||||
set(val) {
|
||||
this.oidc.tokenURL = val
|
||||
// this.$store.state.sso.oidc.tokenURL = val
|
||||
}
|
||||
},
|
||||
userInfoURL: {
|
||||
get() {
|
||||
return this.oidc.userInfoURL
|
||||
return this.$store.state.sso.oidc.userInfoURL
|
||||
},
|
||||
set(val) {
|
||||
this.oidc.userInfoURL = val
|
||||
// this.$store.state.sso.oidc.userInfoURL = val
|
||||
},
|
||||
},
|
||||
clientID: {
|
||||
get() {
|
||||
return this.oidc.clientID
|
||||
return this.$store.state.sso.oidc.clientID
|
||||
},
|
||||
set(val) {
|
||||
this.oidc.clientID = val
|
||||
// this.$store.state.sso.oidc.clientID = val
|
||||
},
|
||||
},
|
||||
clientSecret: {
|
||||
get() {
|
||||
return this.oidc.clientSecret
|
||||
return this.$store.state.sso.oidc.clientSecret
|
||||
},
|
||||
set(val) {
|
||||
this.oidc.clientSecret = val
|
||||
// this.$store.state.sso.oidc.clientSecret = val
|
||||
},
|
||||
},
|
||||
createNewUser: {
|
||||
get() {
|
||||
return this.user.createNewUser
|
||||
return this.$store.state.sso.createNewUser
|
||||
},
|
||||
set(val) {
|
||||
this.user.createNewUser = val
|
||||
// this.$store.state.sso.createNewUser = val
|
||||
},
|
||||
},
|
||||
permissionDownload: {
|
||||
get() {
|
||||
return this.user.permissions.download
|
||||
return this.$store.state.sso.permissions.download
|
||||
},
|
||||
set(val) {
|
||||
this.user.permissions.download = val
|
||||
// this.$store.state.sso.permissions.download = val
|
||||
},
|
||||
},
|
||||
permissionUpdate: {
|
||||
get() {
|
||||
return this.user.permissions.update
|
||||
return this.$store.state.sso.permissions.update
|
||||
},
|
||||
set(val) {
|
||||
this.user.permissions.update = val
|
||||
// this.$store.state.sso.permissions.update = val
|
||||
},
|
||||
},
|
||||
permissionDelete: {
|
||||
get() {
|
||||
return this.user.permissions.delete
|
||||
return this.$store.state.sso.permissions.delete
|
||||
},
|
||||
set(val) {
|
||||
this.user.permissions.delete = val
|
||||
// this.$store.state.sso.permissions.delete = val
|
||||
},
|
||||
},
|
||||
permissionUpload: {
|
||||
get() {
|
||||
return this.user.permissions.upload
|
||||
return this.$store.state.sso.permissions.upload
|
||||
},
|
||||
set(val) {
|
||||
this.user.permissions.upload = val
|
||||
// this.$store.state.sso.permissions.upload = val
|
||||
}
|
||||
},
|
||||
permissionAccessAllLibraries: {
|
||||
get() {
|
||||
return this.user.permissions.accessAllLibraries
|
||||
return this.$store.state.sso.permissions.accessAllLibraries
|
||||
},
|
||||
set(val) {
|
||||
this.user.permissions.accessAllLibraries = val
|
||||
// this.$store.state.sso.permissions.accessAllLibraries = val
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateSSOIssuer(val) {
|
||||
this.oidc.issuer = val
|
||||
},
|
||||
updateAuthorizationURL(val) {
|
||||
this.oidc.authorizationURL = val
|
||||
},
|
||||
updateTokenURL(val) {
|
||||
this.oidc.tokenURL = val
|
||||
},
|
||||
updateUserInfoURL(val) {
|
||||
this.oidc.userInfoURL = val
|
||||
},
|
||||
updateClientID(val) {
|
||||
this.oidc.clientID = val
|
||||
},
|
||||
updateClientSecret(val) {
|
||||
this.oidc.clientSecret = val
|
||||
},
|
||||
updatePermissionCreateNewUser(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
updatePermissionDownload(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
updatePermissionUpdate(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
updatePermissionDelete(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
updatePermissionUpload(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
updatePermissionAccessAllLibraries(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
updatePermissionCreateNewUser(val) {
|
||||
this.permissions.createNewUser = val
|
||||
},
|
||||
saveSSOSettings(payload) {
|
||||
this.updatingSSOSettings = true
|
||||
this.$store
|
||||
.dispatch('sso/updateSSOSettings', {oidc: this.oidc, permissions: this.permissions})
|
||||
.dispatch('sso/updateSSOSettings', {oidc: this.oidc, user: this.user})
|
||||
.then((success) => {
|
||||
console.log('Updated SSO Settings', success)
|
||||
this.updatingSSOSettings = false
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -171,20 +264,21 @@ export default {
|
||||
})
|
||||
},
|
||||
initSSOSettings() {
|
||||
this.newSSOSettings = this.SSOSettings ? { ...this.SSOSettings } : {}
|
||||
for (const key in this.$store.state.sso.oidc) {
|
||||
this.oidc[key] = this.$store.state.sso.oidc[key]
|
||||
}
|
||||
|
||||
|
||||
this.oidc.issuer = this.newSSOSettings.issuer
|
||||
this.oidc.authorizationURL = this.newSSOSettings.authorizationURL
|
||||
this.oidc.tokenURL = this.newSSOSettings.tokenURL
|
||||
this.oidc.userInfoURL = this.newSSOSettings.userInfoURL
|
||||
this.oidc.clientID = this.newSSOSettings.clientID
|
||||
this.oidc.clientSecret = this.newSSOSettings.clientSecret
|
||||
this.updatingSSOSettings = this.newSSOSettings.updatingSSOSettings
|
||||
|
||||
// this.newSSOSettings.coverDestination === this.$constants.CoverDestination.AUDIOBOOK
|
||||
// this.useSquareBookCovers = this.newSSOSettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE
|
||||
// this.useAlternativeBookshelfView = this.newSSOSettings.bookshelfView === this.$constants.BookshelfView.TITLES
|
||||
for (const key in this.$store.state.sso.user) {
|
||||
if (typeof this.$store.state.sso.user[key] === "object" && typeof this.user[key] === "object") {
|
||||
for (const key2 in this.$store.state.sso.user[key]) {
|
||||
this.user[key][key2] = this.$store.state.sso.user[key][key2]
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (this.user[key] !== undefined) {
|
||||
this.user[key] = this.$store.state.sso.user[key]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
@ -111,7 +111,6 @@ export default {
|
||||
this.$axios
|
||||
.$post('/api/authorize', null, {})
|
||||
.then((res) => {
|
||||
console.log({res})
|
||||
this.setUser(res.user)
|
||||
this.processing = false
|
||||
})
|
||||
|
@ -87,20 +87,21 @@ export const actions = {
|
||||
|
||||
export const mutations = {
|
||||
setSSOSettings(state, settings) {
|
||||
if (!settings) return
|
||||
if (!settings || !settings.oidc || !settings.user) return
|
||||
|
||||
for (const key in settings) {
|
||||
if (state.oidc[key] !== settings[key]) {
|
||||
state.oidc[key] = settings[key]
|
||||
}
|
||||
for (const key in settings.oidc) {
|
||||
state.oidc[key] = settings.oidc[key]
|
||||
}
|
||||
},
|
||||
setUserPermissions(state, permissions) {
|
||||
if (!permissions) return
|
||||
|
||||
for (const key in permissions) {
|
||||
if (state.user.permissions[key] !== permissions[key]) {
|
||||
state.user.permissions[key] = permissions[key]
|
||||
for (const key in settings.user) {
|
||||
if (typeof settings.user[key] === "object" && typeof state.user[key] === "object") {
|
||||
for (const key2 in settings.user[key]) {
|
||||
state.user[key][key2] = settings.user[key][key2]
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (state.user[key] !== undefined) {
|
||||
state.user[key] = settings.user[key]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -297,18 +297,20 @@ class ApiController {
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
let SSOUpdate = req.body
|
||||
Logger.debug("SSOUpdate=", SSOUpdate)
|
||||
if (!SSOUpdate || !isObject(SSOUpdate)) {
|
||||
return res.status(500).send('Invalid settings update object')
|
||||
}
|
||||
|
||||
console.log("SSOUpdate", JSON.stringify(SSOUpdate))
|
||||
|
||||
var madeUpdates = this.db.SSOSettings.update(SSOUpdate)
|
||||
console.log("SSOUpdate", JSON.stringify(this.db.SSOSettings))
|
||||
if (madeUpdates) {
|
||||
await this.db.updateEntity('sso', this.db.SSOUpdate)
|
||||
await this.db.updateEntity('settings', this.db.SSOSettings)
|
||||
}
|
||||
return res.json({
|
||||
success: true,
|
||||
SSOUpdate: this.db.SSOUpdate
|
||||
SSOUpdate: this.db.SSOSettings
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -217,11 +217,12 @@ class Auth {
|
||||
|
||||
async handleOIDCVerification(issuer, profile, cb) {
|
||||
Logger.debug(`[Auth] handleOIDCVerification ${issuer}`)
|
||||
let user = this.db.users.find(u => u.id === profile.id)
|
||||
if (!user && this.db.SSOSettings.createNewUser) {
|
||||
let user = this.db.users.find(u => u.ssoId === profile.id)
|
||||
if (!user && this.db.SSOSettings.user.createNewUser) {
|
||||
// create a user
|
||||
let account = {}
|
||||
account.id = profile.id
|
||||
account.id = profile.username
|
||||
account.ssoId = profile.id
|
||||
account.username = profile.username
|
||||
account.isActive = true
|
||||
account.type = "guest"
|
||||
|
@ -85,6 +85,9 @@ class Server {
|
||||
return client.user.toJSONForPublic(this.streamManager.streams)
|
||||
})
|
||||
}
|
||||
get SSOSettings() {
|
||||
return this.db.SSOSettings
|
||||
}
|
||||
|
||||
getClientsForUser(userId) {
|
||||
return Object.values(this.clients).filter(c => c.user && c.user.id === userId)
|
||||
@ -679,6 +682,7 @@ class Server {
|
||||
}
|
||||
if (user.type === 'root') {
|
||||
initialPayload.usersOnline = this.usersOnline
|
||||
initialPayload.SSOSettings = this.SSOSettings
|
||||
}
|
||||
client.socket.emit('init', initialPayload)
|
||||
|
||||
|
@ -1,22 +1,51 @@
|
||||
const Logger = require('../Logger')
|
||||
const User = require('./User')
|
||||
const { isObject } = require('../utils')
|
||||
const { difference } = require('../utils/string')
|
||||
|
||||
const defaultSettings = {
|
||||
createNewUser: false,
|
||||
userPermissions: User.getDefaultUserPermissions('guest')
|
||||
user: {
|
||||
createNewUser: false,
|
||||
isActive: true,
|
||||
settings: {
|
||||
mobileOrderBy: 'recent',
|
||||
mobileOrderDesc: true,
|
||||
mobileFilterBy: 'all',
|
||||
orderBy: 'book.title',
|
||||
orderDesc: false,
|
||||
filterBy: 'all',
|
||||
playbackRate: 1,
|
||||
bookshelfCoverSize: 120,
|
||||
collapseSeries: false
|
||||
},
|
||||
permissions: User.getDefaultUserPermissions('guest')
|
||||
}
|
||||
}
|
||||
|
||||
class SSOSettings {
|
||||
constructor(settings = defaultSettings) {
|
||||
this.id = 'sso-settings'
|
||||
this.createNewUser = !!settings.createNewUser
|
||||
this.userPermissions = { ...settings.userPermissions }
|
||||
this.initOIDCSettings();
|
||||
this.user = { ...settings.user }
|
||||
this.initOIDCSettings(settings);
|
||||
Logger.debug("[SSOSettings.constructor]", this.toJSON)
|
||||
}
|
||||
|
||||
initOIDCSettings() {
|
||||
initOIDCSettings(settings) {
|
||||
// can't be part of default settings, because apperently process.env is not set in the beginning
|
||||
if (settings && settings.oidc) {
|
||||
this.oidc = {
|
||||
issuer: settings.oidc.issuer,
|
||||
authorizationURL: settings.oidc.authorizationURL,
|
||||
tokenURL: settings.oidc.tokenURL,
|
||||
userInfoURL: settings.oidc.userInfoURL,
|
||||
clientID: settings.oidc.clientID,
|
||||
clientSecret: settings.oidc.clientSecret,
|
||||
callbackURL: "/oidc/callback",
|
||||
scope: "openid email profile"
|
||||
}
|
||||
return
|
||||
}
|
||||
this.oidc = {
|
||||
issuer: process.env.OIDC_ISSUER || '',
|
||||
authorizationURL: process.env.OIDC_AUTHORIZATION_URL || '',
|
||||
@ -34,17 +63,28 @@ class SSOSettings {
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
const tmp = {
|
||||
id: this.id,
|
||||
oidc: { ...this.oidc },
|
||||
createNewUser: this.createNewUser,
|
||||
userPermissions: { ...this.userPermissions }
|
||||
user: { ...this.user }
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
update(payload) {
|
||||
let hasUpdates = false
|
||||
const oldTmp = JSON.stringify(this.toJSON())
|
||||
const newTmp = JSON.stringify(payload) // deep copy "for free"
|
||||
const hasUpdates = difference(oldTmp, newTmp) !== ""; // Not very efficient, but ok for small objects
|
||||
Logger.debug(`SSOSettings hasUpdates=${hasUpdates}`)
|
||||
if (!hasUpdates) return hasUpdates
|
||||
|
||||
payload = JSON.parse(newTmp)
|
||||
this.oidc = payload.oidc
|
||||
this.user = payload.user
|
||||
return hasUpdates
|
||||
Logger.debug("SSOSettings.update", payload, this)
|
||||
for (const key in payload) {
|
||||
Logger.debug(`key: ${key}: ${JSON.stringify(payload[key])}`)
|
||||
if (isObject(payload[key])) {
|
||||
for (const setting in payload[key]) {
|
||||
if (!this[key] || this[key][setting] === payload[key][setting]) {
|
||||
@ -58,12 +98,13 @@ class SSOSettings {
|
||||
hasUpdates = true
|
||||
}
|
||||
}
|
||||
Logger.debug("SSOSettings.update", hasUpdates, this)
|
||||
return hasUpdates
|
||||
}
|
||||
|
||||
getNewUserPermissions() {
|
||||
return {
|
||||
...this.userPermissions
|
||||
...this.user.permissions
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ class User {
|
||||
this.lastSeen = null
|
||||
this.createdAt = null
|
||||
this.audiobooks = null
|
||||
this.ssoId = null
|
||||
|
||||
this.settings = {}
|
||||
this.permissions = {}
|
||||
@ -84,6 +85,7 @@ class User {
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
ssoId: this.ssoId,
|
||||
username: this.username,
|
||||
pash: this.pash,
|
||||
type: this.type,
|
||||
@ -138,6 +140,7 @@ class User {
|
||||
this.type = user.type
|
||||
this.stream = user.stream || null
|
||||
this.token = user.token
|
||||
this.ssoId = user.ssoId || ""
|
||||
if (user.audiobooks) {
|
||||
this.audiobooks = {}
|
||||
for (const key in user.audiobooks) {
|
||||
|
Loading…
Reference in New Issue
Block a user