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() {
|
async hash() {
|
||||||
const line = await this._host.run_line_result(`sha256sum ${this._path}`)
|
const line = await this._host.run_line_result(`sha256sum ${this._path}`)
|
||||||
return line.split(' ')[0]
|
return line.split(' ')[0]
|
||||||
|
@ -24,6 +24,12 @@ class Host extends Injectable {
|
|||||||
_resolve_path_command = `readlink -f "%%PATH%%"`
|
_resolve_path_command = `readlink -f "%%PATH%%"`
|
||||||
_reboot_command = `reboot`
|
_reboot_command = `reboot`
|
||||||
_change_directory_command = `cd "%%PATH%%"`
|
_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) {
|
constructor(config) {
|
||||||
super()
|
super()
|
||||||
@ -117,6 +123,39 @@ class Host extends Injectable {
|
|||||||
return this.run_line_result(this._resolve_path_command.replace('%%PATH%%', resource_path))
|
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() {
|
async get_mount_points() {
|
||||||
const result = await this.execute(this._list_mount_points_command)
|
const result = await this.execute(this._list_mount_points_command)
|
||||||
if ( result.exit_code !== 0 ) {
|
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 {
|
class StatesService extends Service {
|
||||||
static #state_map = {
|
static #state_map = {
|
||||||
// TODO apache and nginx states - virtual host, reverse proxy
|
// TODO apache and nginx states - virtual host, reverse proxy
|
||||||
// TODO file/directory permissions state - chmod & chown
|
|
||||||
// TODO file pack state - zip, tarball
|
// TODO file pack state - zip, tarball
|
||||||
// TODO package repository states - import keys, install repository
|
// TODO package repository states - import keys, install repository
|
||||||
// TODO service manager states - service enabled, service installed
|
// TODO service manager states - service enabled, service installed
|
||||||
@ -21,6 +20,8 @@ class StatesService extends Service {
|
|||||||
'fs.file': require('../classes/state/fs/FileState'),
|
'fs.file': require('../classes/state/fs/FileState'),
|
||||||
'fs.directory': require('../classes/state/fs/DirectoryState'),
|
'fs.directory': require('../classes/state/fs/DirectoryState'),
|
||||||
'fs.unpack': require('../classes/state/fs/UnpackState'),
|
'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.present': require('../classes/state/os/PackageState'),
|
||||||
'package.updates': require('../classes/state/os/UpdateState'),
|
'package.updates': require('../classes/state/os/UpdateState'),
|
||||||
|
Loading…
Reference in New Issue
Block a user