diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 5ea53da80..b644db108 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -35,6 +35,6 @@ > > In case of conflict, the highest (lowest in previous list) `$version` wins. -- xo-server-audit patch +- xo-server-audit minor - xo-vmdk-to-vhd patch - xo-web minor diff --git a/packages/xo-server-audit/src/index.js b/packages/xo-server-audit/src/index.js index 574af83ac..eecd5e191 100644 --- a/packages/xo-server-audit/src/index.js +++ b/packages/xo-server-audit/src/index.js @@ -19,6 +19,7 @@ const DEFAULT_BLOCKED_LIST = { 'acl.get': true, 'acl.getCurrentPermissions': true, 'audit.checkIntegrity': true, + 'audit.clean': true, 'audit.generateFingerprint': true, 'audit.getRecords': true, 'backup.list': true, @@ -114,6 +115,30 @@ class Db extends Storage { getLastId() { return this.get(LAST_ID) } + + async clean() { + const db = this._db + + // delete first so that a new chain can be constructed even if anything else fails + await db.del(LAST_ID) + + return new Promise((resolve, reject) => { + let count = 1 + const cb = () => { + if (--count === 0) { + resolve() + } + } + const deleteEntry = key => { + ++count + db.del(key, cb) + } + db.createKeyStream() + .on('data', deleteEntry) + .on('end', cb) + .on('error', reject) + }) + } } export const configurationSchema = { @@ -209,10 +234,15 @@ class AuditXoPlugin { cleaners.push(() => uploadLastHashJob.stop()) } + const clean = this._storage.clean.bind(this._storage) + clean.permission = 'admin' + clean.description = 'Clean audit database' + cleaners.push( this._xo.addApiMethods({ audit: { checkIntegrity, + clean, exportRecords, generateFingerprint, getRecords,