feat(xo-server-audit): add active setting (default false) (#5151)
This commit is contained in:
parent
e1bf68ab38
commit
f51bcfa05a
@ -7,6 +7,8 @@
|
||||
|
||||
> Users must be able to say: “Nice enhancement, I'm eager to test it”
|
||||
|
||||
- [Audit] Logging user actions is now opt-in (PR [#5151](https://github.com/vatesfr/xen-orchestra/pull/5151))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
> Users must be able to say: “I had this issue, happy to know it's fixed”
|
||||
@ -33,5 +35,6 @@
|
||||
>
|
||||
> In case of conflict, the highest (lowest in previous list) `$version` wins.
|
||||
|
||||
- xo-server-audit minor
|
||||
- xo-web patch
|
||||
- xo-server patch
|
||||
|
@ -115,6 +115,16 @@ class Db extends Storage {
|
||||
}
|
||||
}
|
||||
|
||||
export const configurationSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
active: {
|
||||
description: 'Whether to save user actions in the audit log',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const NAMESPACE = 'audit'
|
||||
class AuditXoPlugin {
|
||||
constructor({ staticConfig, xo }) {
|
||||
@ -127,6 +137,19 @@ class AuditXoPlugin {
|
||||
|
||||
this._auditCore = undefined
|
||||
this._storage = undefined
|
||||
|
||||
this._listeners = {
|
||||
'xo:audit': this._handleEvent.bind(this),
|
||||
'xo:postCall': this._handleEvent.bind(this, 'apiCall'),
|
||||
}
|
||||
}
|
||||
|
||||
configure({ active = false }, { loaded }) {
|
||||
this._active = active
|
||||
|
||||
if (loaded) {
|
||||
this._addListeners()
|
||||
}
|
||||
}
|
||||
|
||||
async load() {
|
||||
@ -139,8 +162,7 @@ class AuditXoPlugin {
|
||||
this._storage = undefined
|
||||
})
|
||||
|
||||
this._addListener('xo:postCall', this._handleEvent.bind(this, 'apiCall'))
|
||||
this._addListener('xo:audit', this._handleEvent.bind(this))
|
||||
this._addListeners()
|
||||
|
||||
const exportRecords = this._exportRecords.bind(this)
|
||||
exportRecords.permission = 'admin'
|
||||
@ -184,34 +206,44 @@ class AuditXoPlugin {
|
||||
}
|
||||
|
||||
unload() {
|
||||
this._removeListeners()
|
||||
this._cleaners.forEach(cleaner => cleaner())
|
||||
this._cleaners.length = 0
|
||||
}
|
||||
|
||||
_addListener(event, listener_) {
|
||||
const listener = async (...args) => {
|
||||
try {
|
||||
await listener_(...args)
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
}
|
||||
_addListeners(event, listener_) {
|
||||
this._removeListeners()
|
||||
|
||||
if (this._active) {
|
||||
const listeners = this._listeners
|
||||
Object.keys(listeners).forEach(event => {
|
||||
this._xo.addListener(event, listeners[event])
|
||||
})
|
||||
}
|
||||
const xo = this._xo
|
||||
xo.on(event, listener)
|
||||
this._cleaners.push(() => xo.removeListener(event, listener))
|
||||
}
|
||||
|
||||
_handleEvent(event, { userId, userIp, userName, ...data }) {
|
||||
if (event !== 'apiCall' || !this._blockedList[data.method]) {
|
||||
return this._auditCore.add(
|
||||
{
|
||||
userId,
|
||||
userIp,
|
||||
userName,
|
||||
},
|
||||
event,
|
||||
data
|
||||
)
|
||||
_removeListeners() {
|
||||
const listeners = this._listeners
|
||||
Object.keys(listeners).forEach(event => {
|
||||
this._xo.removeListener(event, listeners[event])
|
||||
})
|
||||
}
|
||||
|
||||
async _handleEvent(event, { userId, userIp, userName, ...data }) {
|
||||
try {
|
||||
if (event !== 'apiCall' || !this._blockedList[data.method]) {
|
||||
return await this._auditCore.add(
|
||||
{
|
||||
userId,
|
||||
userIp,
|
||||
userName,
|
||||
},
|
||||
event,
|
||||
data
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user