mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
274b0e48be
This patch slightly changes the behavior of the `AUDIOBOOKSHELF_UID` and `AUDIOBOOKSHELF_GID` options. Instead of defining a default user and group, trying to modify files and silently failing if the filesystem mode cannot be changed, this patch will just skip the entire process in the first place. If these options are defined, Audiobookshelf should behave exactly as before. If they are not defined, Audiobookshelf will now cause fewer file modifications (or less failures when trying to modify files). If this patch gets applied, it should probably be highlighted in the release notes. This usually shouldn't cause problems for migrations since the Docker guides explicitly configure the options and the package installations do not seem to use this at all, but there is still a change that it will and users should be aware of that. If a problem arises, users can easily fix the problem by either setting the permissions once manually to the audiobookshelf user or by simply defining the `AUDIOBOOKSHELF_UID/GID` options.
122 lines
3.4 KiB
JavaScript
122 lines
3.4 KiB
JavaScript
const fs = require('../libs/fsExtra')
|
|
const Path = require('path')
|
|
const Logger = require('../Logger')
|
|
|
|
// Modified from:
|
|
// https://github.com/isaacs/chmodr/blob/master/chmodr.js
|
|
|
|
// If a party has r, add x
|
|
// so that dirs are listable
|
|
const dirMode = mode => {
|
|
if (mode & 0o400)
|
|
mode |= 0o100
|
|
if (mode & 0o40)
|
|
mode |= 0o10
|
|
if (mode & 0o4)
|
|
mode |= 0o1
|
|
return mode
|
|
}
|
|
|
|
const chmodrKid = (p, child, mode, uid, gid, cb) => {
|
|
if (typeof child === 'string')
|
|
return fs.lstat(Path.resolve(p, child), (er, stats) => {
|
|
if (er)
|
|
return cb(er)
|
|
stats.name = child
|
|
chmodrKid(p, stats, mode, uid, gid, cb)
|
|
})
|
|
|
|
if (child.isDirectory()) {
|
|
chmodr(Path.resolve(p, child.name), mode, uid, gid, er => {
|
|
if (er)
|
|
return cb(er)
|
|
|
|
var _path = Path.resolve(p, child.name)
|
|
fs.chmod(_path, dirMode(mode)).then(() => {
|
|
fs.chown(_path, uid, gid, cb)
|
|
})
|
|
})
|
|
} else {
|
|
var _path = Path.resolve(p, child.name)
|
|
fs.chmod(_path, mode).then(() => {
|
|
fs.chown(_path, uid, gid, cb)
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
const chmodr = (p, mode, uid, gid, cb) => {
|
|
fs.readdir(p, { withFileTypes: true }, (er, children) => {
|
|
// any error other than ENOTDIR means it's not readable, or
|
|
// doesn't exist. give up.
|
|
if (er && er.code !== 'ENOTDIR') return cb(er)
|
|
if (er) { // Is a file
|
|
return fs.chmod(p, mode).then(() => {
|
|
fs.chown(p, uid, gid, cb)
|
|
})
|
|
}
|
|
if (!children.length) {
|
|
return fs.chmod(p, dirMode(mode)).then(() => {
|
|
fs.chown(p, uid, gid, cb)
|
|
})
|
|
}
|
|
|
|
let len = children.length
|
|
let errState = null
|
|
const then = er => {
|
|
if (errState) return
|
|
if (er) return cb(errState = er)
|
|
if (--len === 0) {
|
|
return fs.chmod(p, dirMode(mode)).then(() => {
|
|
fs.chown(p, uid, gid, cb)
|
|
})
|
|
}
|
|
}
|
|
|
|
children.forEach(child => chmodrKid(p, child, mode, uid, gid, then))
|
|
})
|
|
}
|
|
|
|
// Set custom permissions
|
|
module.exports.set = (path, mode, uid, gid, silent = false) => {
|
|
return new Promise((resolve) => {
|
|
if (!silent) Logger.debug(`[FilePerms] Setting permission "${mode}" for uid ${uid} and gid ${gid} | "${path}"`)
|
|
chmodr(path, mode, uid, gid, resolve)
|
|
})
|
|
}
|
|
|
|
// Default permissions 0o744 and global Uid/Gid
|
|
module.exports.setDefault = (path, silent = false) => {
|
|
const mode = 0o744
|
|
const uid = global.Uid
|
|
const gid = global.Gid
|
|
return new Promise((resolve) => {
|
|
if (isNaN(uid) || isNaN(gid)) {
|
|
if (!silent) Logger.debug('Not modifying permissions since no uid/gid is specified')
|
|
return resolve()
|
|
}
|
|
if (!silent) Logger.debug(`Setting permission "${mode}" for uid ${uid} and gid ${gid} | "${path}"`)
|
|
chmodr(path, mode, uid, gid, resolve)
|
|
})
|
|
}
|
|
|
|
// Default permissions 0o744 and global Uid/Gid
|
|
// Used for setting default permission to initial config/metadata directories
|
|
module.exports.setDefaultDirSync = (path, silent = false) => {
|
|
const mode = 0o744
|
|
const uid = global.Uid
|
|
const gid = global.Gid
|
|
if (isNaN(uid) || isNaN(gid)) {
|
|
if (!silent) Logger.debug('Not modifying permissions since no uid/gid is specified')
|
|
return true
|
|
}
|
|
if (!silent) Logger.debug(`[FilePerms] Setting dir permission "${mode}" for uid ${uid} and gid ${gid} | "${path}"`)
|
|
try {
|
|
fs.chmodSync(path, mode)
|
|
fs.chownSync(path, uid, gid)
|
|
return true
|
|
} catch (error) {
|
|
Logger.error(`[FilePerms] Error setting dir permissions for path "${path}"`, error)
|
|
return false
|
|
}
|
|
} |