Add OwnerState and PermissionState
This commit is contained in:
parent
2725f9eac2
commit
6f1de65602
@ -154,6 +154,24 @@ class UniversalPath extends Injectable {
|
||||
})
|
||||
}
|
||||
|
||||
async permissions(set_level = false, recursive = false) {
|
||||
if ( set_level ) {
|
||||
await this._host.set_permissions_for_path(this, set_level, recursive)
|
||||
} else {
|
||||
return this._host.get_permissions_for_path(this)
|
||||
}
|
||||
}
|
||||
|
||||
async ownership(set_owners = false, recursive = false) {
|
||||
if ( set_owners ) {
|
||||
const current = await this.ownership()
|
||||
const target = {...current, ...set_owners}
|
||||
await this._host.set_ownership_for_path(this, target, recursive)
|
||||
} else {
|
||||
return this._host.get_ownership_for_path(this)
|
||||
}
|
||||
}
|
||||
|
||||
async hash() {
|
||||
const line = await this._host.run_line_result(`sha256sum ${this._path}`)
|
||||
return line.split(' ')[0]
|
||||
|
@ -24,6 +24,12 @@ class Host extends Injectable {
|
||||
_resolve_path_command = `readlink -f "%%PATH%%"`
|
||||
_reboot_command = `reboot`
|
||||
_change_directory_command = `cd "%%PATH%%"`
|
||||
_file_directory_permission_fetch_command = `stat -c %a "%%PATH%%"`
|
||||
_file_directory_permission_set_command_flat = `chmod %%LEVEL%% "%%PATH%%"`
|
||||
_file_directory_permission_set_command_recursive = `chmod -R %%LEVEL%% "%%PATH%%"`
|
||||
_file_directory_ownership_fetch_command = `stat -c "%U:%G" "%%PATH%%"`
|
||||
_file_directory_ownership_set_command_flat = `chown %%OWNERS%% "%%PATH%%"`
|
||||
_file_directory_ownership_set_command_recursive = `chown -R %%OWNERS%% "%%PATH%%"`
|
||||
|
||||
constructor(config) {
|
||||
super()
|
||||
@ -117,6 +123,39 @@ class Host extends Injectable {
|
||||
return this.run_line_result(this._resolve_path_command.replace('%%PATH%%', resource_path))
|
||||
}
|
||||
|
||||
async get_permissions_for_path(resource_path) {
|
||||
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
|
||||
return this.run_line_result(this._file_directory_permission_fetch_command.replace('%%PATH%%', resource_path))
|
||||
}
|
||||
|
||||
async set_permissions_for_path(resource_path, level, recursive = false) {
|
||||
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
|
||||
let cmd
|
||||
if ( recursive ) cmd = this._file_directory_permission_set_command_recursive
|
||||
else cmd = this._file_directory_permission_set_command_flat
|
||||
cmd = cmd.replace('%%PATH%%', resource_path)
|
||||
cmd = cmd.replace('%%LEVEL%%', level)
|
||||
await this.run(cmd)
|
||||
}
|
||||
|
||||
async get_ownership_for_path(resource_path) {
|
||||
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
|
||||
const cmd = this._file_directory_ownership_fetch_command.replace('%%PATH%%', resource_path)
|
||||
const result = await this.run_line_result(cmd)
|
||||
const parts = result.split(':')
|
||||
return {user: parts[0], group: parts[1]}
|
||||
}
|
||||
|
||||
async set_ownership_for_path(resource_path, { user, group }, recursive = false) {
|
||||
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
|
||||
let cmd
|
||||
if ( recursive ) cmd = this._file_directory_ownership_set_command_recursive
|
||||
else cmd = this._file_directory_ownership_set_command_flat
|
||||
cmd = cmd.replace('%%PATH%%', resource_path)
|
||||
cmd = cmd.replace('%%OWNERS%%', `${user}:${group}`)
|
||||
await this.run(cmd)
|
||||
}
|
||||
|
||||
async get_mount_points() {
|
||||
const result = await this.execute(this._list_mount_points_command)
|
||||
if ( result.exit_code !== 0 ) {
|
||||
|
44
app/classes/state/fs/OwnerState.js
Normal file
44
app/classes/state/fs/OwnerState.js
Normal file
@ -0,0 +1,44 @@
|
||||
const State = require('../State')
|
||||
|
||||
class OwnerState extends State {
|
||||
static get services() {
|
||||
return [...super.services, 'output']
|
||||
}
|
||||
|
||||
async apply() {
|
||||
if ( !(await this.check()) ) {
|
||||
const path = await this._path()
|
||||
await path.ownership(this._config.owners, !!this._config.recursive)
|
||||
}
|
||||
}
|
||||
|
||||
async check() {
|
||||
const path = await this._path()
|
||||
const owners = await path.ownership()
|
||||
|
||||
if ( this._config.owners.user && owners.user !== this._config.owners.user ) return false
|
||||
else if ( this._config.owners.group && owners.group !== this._config.owners.group ) return false
|
||||
return true
|
||||
}
|
||||
|
||||
async reverse() {
|
||||
if ( await this.check() ) {
|
||||
if (this._config.revert_to) {
|
||||
const path = await this._path()
|
||||
await path.ownership(this._config.revert_to, !!this._config.recursive)
|
||||
} else {
|
||||
this.output.warn(`Owner state does not support automatic reversal. Specify the revert_to config key for this functionality. (Host: ${this._host.name})`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _path() {
|
||||
const path = await this._host.get_path(this._config.path)
|
||||
await path.classify()
|
||||
if ( !path.is_valid() ) throw new Error(`Invalid path for OwnerState: ${path}`)
|
||||
return path
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = OwnerState
|
39
app/classes/state/fs/PermissionState.js
Normal file
39
app/classes/state/fs/PermissionState.js
Normal file
@ -0,0 +1,39 @@
|
||||
const State = require('../State')
|
||||
|
||||
class PermissionState extends State {
|
||||
static get services() {
|
||||
return [...super.services, 'output']
|
||||
}
|
||||
|
||||
async apply() {
|
||||
if ( !(await this.check()) ) {
|
||||
const path = await this._path()
|
||||
await path.permissions(this._config.level, !!this._config.recursive)
|
||||
}
|
||||
}
|
||||
|
||||
async check() {
|
||||
const path = await this._path()
|
||||
const permissions = `${await path.permissions()}`.trim()
|
||||
const target = `${this._config.level}`.trim()
|
||||
return permissions === target
|
||||
}
|
||||
|
||||
async reverse() {
|
||||
if ( this._config.revert_to ) {
|
||||
const path = await this._path()
|
||||
await path.permissions(this._config.revert_to, this._config.recursive)
|
||||
} else {
|
||||
this.output.warn(`Permission state does not support automatic reversal. Specify the revert_to config for this functionality. (Host: ${this._host.name})`)
|
||||
}
|
||||
}
|
||||
|
||||
async _path() {
|
||||
const path = await this._host.get_path(this._config.path)
|
||||
await path.classify()
|
||||
if ( !path.is_valid() ) throw new Error(`Invalid path for PermissionState: ${path}`)
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = PermissionState
|
@ -12,7 +12,6 @@ const { Service } = require('flitter-di')
|
||||
class StatesService extends Service {
|
||||
static #state_map = {
|
||||
// TODO apache and nginx states - virtual host, reverse proxy
|
||||
// TODO file/directory permissions state - chmod & chown
|
||||
// TODO file pack state - zip, tarball
|
||||
// TODO package repository states - import keys, install repository
|
||||
// TODO service manager states - service enabled, service installed
|
||||
@ -21,6 +20,8 @@ class StatesService extends Service {
|
||||
'fs.file': require('../classes/state/fs/FileState'),
|
||||
'fs.directory': require('../classes/state/fs/DirectoryState'),
|
||||
'fs.unpack': require('../classes/state/fs/UnpackState'),
|
||||
'fs.permission': require('../classes/state/fs/PermissionState'),
|
||||
'fs.ownership': require('../classes/state/fs/OwnerState'),
|
||||
|
||||
'package.present': require('../classes/state/os/PackageState'),
|
||||
'package.updates': require('../classes/state/os/UpdateState'),
|
||||
|
Loading…
Reference in New Issue
Block a user