feat(xo-server/xo.exportConfig): new compress=true param

This commit is contained in:
Julien Fontanet 2023-04-21 17:03:12 +02:00
parent 76a91cc5e9
commit a956cb2ac9
3 changed files with 20 additions and 6 deletions

View File

@ -25,7 +25,7 @@
"xo-server-recover-account": "dist/recover-account-cli.mjs"
},
"engines": {
"node": ">=14.17"
"node": ">=14.18"
},
"dependencies": {
"@iarna/toml": "^2.2.1",

View File

@ -15,8 +15,11 @@ clean.permission = 'admin'
// -------------------------------------------------------------------
export async function exportConfig({ entries, passphrase }) {
export async function exportConfig({ compress, entries, passphrase }) {
let suffix = '/config.json'
if (compress) {
suffix += '.gz'
}
if (passphrase !== undefined) {
suffix += '.enc'
}
@ -26,10 +29,9 @@ export async function exportConfig({ entries, passphrase }) {
(req, res) => {
res.set({
'content-disposition': 'attachment',
'content-type': 'application/json',
})
return this.exportConfig({ entries, passphrase })
return this.exportConfig({ compress, entries, passphrase })
},
undefined,
{ suffix }
@ -40,6 +42,7 @@ export async function exportConfig({ entries, passphrase }) {
exportConfig.permission = 'admin'
exportConfig.params = {
compress: { type: 'boolean', default: true },
entries: { type: 'array', items: { type: 'string' }, optional: true },
passphrase: { type: 'string', optional: true },
}

View File

@ -1,6 +1,8 @@
import * as openpgp from 'openpgp'
import DepTree from 'deptree'
import fromCallback from 'promise-toolbox/fromCallback'
import { createLogger } from '@xen-orchestra/log'
import { gunzip, gzip } from 'node:zlib'
import { asyncMapValues } from '../_asyncMapValues.mjs'
@ -23,7 +25,7 @@ export default class ConfigManagement {
this._managers[id] = { dependencies, exporter, importer }
}
async exportConfig({ entries, passphrase } = {}) {
async exportConfig({ compress = false, entries, passphrase } = {}) {
let managers = this._managers
if (entries !== undefined) {
const subset = { __proto__: null }
@ -39,11 +41,15 @@ export default class ConfigManagement {
let config = JSON.stringify(await asyncMapValues(managers, ({ exporter }) => exporter()))
if (compress) {
config = await fromCallback(gzip, config)
}
if (passphrase !== undefined) {
config = Buffer.from(
await openpgp.encrypt({
format: 'binary',
message: await openpgp.createMessage({ text: config }),
message: await openpgp.createMessage(typeof config === 'string' ? { text: config } : { binary: config }),
passwords: passphrase,
})
)
@ -56,12 +62,17 @@ export default class ConfigManagement {
if (passphrase !== undefined) {
config = (
await openpgp.decrypt({
format: 'binary',
message: await openpgp.readMessage({ binaryMessage: config }),
passwords: passphrase,
})
).data
}
if (typeof config !== 'string' && config[0] === 0x1f && config[1] === 0x8b) {
config = await fromCallback(gunzip, config)
}
config = JSON.parse(config)
const managers = this._managers