wikijs-fork/server/modules/storage/disk/storage.js
Adrián Martínez Interactiv4 52304a8149
fix: update storage.js to match pageHelper.injectPageMetadata (#2832)
* Update storage.js to match pageHelper.injectPageMetadata

At pageHelper.injectPageMetadata references editorKey and tags to build metadata, but this data seems not to be supplied to this function, since page object is only built from specified columns.

As a result, tags are always empty when exporting pages, and editor key appears as undefined.

It happens also with git storage, but may happen with another storage providers.

I run into this issue running Wiki.js 2.5.170 with the following Docker stack:

CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS                                         NAMES
39373979b693        requarks/wiki:2                         "docker-entrypoint.s…"   44 minutes ago      Up 9 minutes        0.0.0.0:80->3000/tcp, 0.0.0.0:443->3443/tcp   wiki
608de6278aaa        requarks/wiki-update-companion:latest   "dotnet wiki-update-…"   5 months ago        Up 6 hours          80/tcp                                        wiki-update-companion
12c7b35ba295        postgres:11                             "docker-entrypoint.s…"   5 months ago        Up 6 hours          5432/tcp                                      db

* Provide id to allow to query for tags

* Update git storage to provide editorKey and tags
2021-01-29 14:15:22 -05:00

181 lines
6.6 KiB
JavaScript

const fs = require('fs-extra')
const path = require('path')
const tar = require('tar-fs')
const zlib = require('zlib')
const stream = require('stream')
const _ = require('lodash')
const Promise = require('bluebird')
const pipeline = Promise.promisify(stream.pipeline)
const moment = require('moment')
const pageHelper = require('../../../helpers/page')
const commonDisk = require('./common')
/* global WIKI */
module.exports = {
async activated() {
// not used
},
async deactivated() {
// not used
},
async init() {
WIKI.logger.info('(STORAGE/DISK) Initializing...')
await fs.ensureDir(this.config.path)
WIKI.logger.info('(STORAGE/DISK) Initialization completed.')
},
async sync({ manual } = { manual: false }) {
if (this.config.createDailyBackups || manual) {
const dirPath = path.join(this.config.path, manual ? '_manual' : '_daily')
await fs.ensureDir(dirPath)
const dateFilename = moment().format(manual ? 'YYYYMMDD-HHmmss' : 'DD')
WIKI.logger.info(`(STORAGE/DISK) Creating backup archive...`)
await pipeline(
tar.pack(this.config.path, {
ignore: (filePath) => {
return filePath.indexOf('_daily') >= 0 || filePath.indexOf('_manual') >= 0
}
}),
zlib.createGzip(),
fs.createWriteStream(path.join(dirPath, `wiki-${dateFilename}.tar.gz`))
)
WIKI.logger.info('(STORAGE/DISK) Backup archive created successfully.')
}
},
async created(page) {
WIKI.logger.info(`(STORAGE/DISK) Creating file [${page.localeCode}] ${page.path}...`)
let fileName = `${page.path}.${pageHelper.getFileExtension(page.contentType)}`
if (WIKI.config.lang.code !== page.localeCode) {
fileName = `${page.localeCode}/${fileName}`
}
const filePath = path.join(this.config.path, fileName)
await fs.outputFile(filePath, page.injectMetadata(), 'utf8')
},
async updated(page) {
WIKI.logger.info(`(STORAGE/DISK) Updating file [${page.localeCode}] ${page.path}...`)
let fileName = `${page.path}.${pageHelper.getFileExtension(page.contentType)}`
if (WIKI.config.lang.code !== page.localeCode) {
fileName = `${page.localeCode}/${fileName}`
}
const filePath = path.join(this.config.path, fileName)
await fs.outputFile(filePath, page.injectMetadata(), 'utf8')
},
async deleted(page) {
WIKI.logger.info(`(STORAGE/DISK) Deleting file [${page.localeCode}] ${page.path}...`)
let fileName = `${page.path}.${pageHelper.getFileExtension(page.contentType)}`
if (WIKI.config.lang.code !== page.localeCode) {
fileName = `${page.localeCode}/${fileName}`
}
const filePath = path.join(this.config.path, fileName)
await fs.unlink(filePath)
},
async renamed(page) {
WIKI.logger.info(`(STORAGE/DISK) Renaming file [${page.localeCode}] ${page.path} to [${page.destinationLocaleCode}] ${page.destinationPath}...`)
let sourceFilePath = `${page.path}.${pageHelper.getFileExtension(page.contentType)}`
let destinationFilePath = `${page.destinationPath}.${pageHelper.getFileExtension(page.contentType)}`
if (WIKI.config.lang.namespacing) {
if (WIKI.config.lang.code !== page.localeCode) {
sourceFilePath = `${page.localeCode}/${sourceFilePath}`
}
if (WIKI.config.lang.code !== page.destinationLocaleCode) {
destinationFilePath = `${page.destinationLocaleCode}/${destinationFilePath}`
}
}
await fs.move(path.join(this.config.path, sourceFilePath), path.join(this.config.path, destinationFilePath), { overwrite: true })
},
/**
* ASSET UPLOAD
*
* @param {Object} asset Asset to upload
*/
async assetUploaded (asset) {
WIKI.logger.info(`(STORAGE/DISK) Creating new file ${asset.path}...`)
await fs.outputFile(path.join(this.config.path, asset.path), asset.data)
},
/**
* ASSET DELETE
*
* @param {Object} asset Asset to delete
*/
async assetDeleted (asset) {
WIKI.logger.info(`(STORAGE/DISK) Deleting file ${asset.path}...`)
await fs.remove(path.join(this.config.path, asset.path))
},
/**
* ASSET RENAME
*
* @param {Object} asset Asset to rename
*/
async assetRenamed (asset) {
WIKI.logger.info(`(STORAGE/DISK) Renaming file from ${asset.path} to ${asset.destinationPath}...`)
await fs.move(path.join(this.config.path, asset.path), path.join(this.config.path, asset.destinationPath), { overwrite: true })
},
async getLocalLocation (asset) {
return path.join(this.config.path, asset.path)
},
/**
* HANDLERS
*/
async dump() {
WIKI.logger.info(`(STORAGE/DISK) Dumping all content to disk...`)
// -> Pages
await pipeline(
WIKI.models.knex.column('id', 'path', 'localeCode', 'title', 'description', 'contentType', 'content', 'isPublished', 'updatedAt', 'createdAt', 'editorKey').select().from('pages').where({
isPrivate: false
}).stream(),
new stream.Transform({
objectMode: true,
transform: async (page, enc, cb) => {
const pageObject = await WIKI.models.pages.query().findById(page.id)
page.tags = await pageObject.$relatedQuery('tags')
let fileName = `${page.path}.${pageHelper.getFileExtension(page.contentType)}`
if (WIKI.config.lang.code !== page.localeCode) {
fileName = `${page.localeCode}/${fileName}`
}
WIKI.logger.info(`(STORAGE/DISK) Dumping page ${fileName}...`)
const filePath = path.join(this.config.path, fileName)
await fs.outputFile(filePath, pageHelper.injectPageMetadata(page), 'utf8')
cb()
}
})
)
// -> Assets
const assetFolders = await WIKI.models.assetFolders.getAllPaths()
await pipeline(
WIKI.models.knex.column('filename', 'folderId', 'data').select().from('assets').join('assetData', 'assets.id', '=', 'assetData.id').stream(),
new stream.Transform({
objectMode: true,
transform: async (asset, enc, cb) => {
const filename = (asset.folderId && asset.folderId > 0) ? `${_.get(assetFolders, asset.folderId)}/${asset.filename}` : asset.filename
WIKI.logger.info(`(STORAGE/DISK) Dumping asset ${filename}...`)
await fs.outputFile(path.join(this.config.path, filename), asset.data)
cb()
}
})
)
WIKI.logger.info('(STORAGE/DISK) All content was dumped to disk successfully.')
},
async backup() {
return this.sync({ manual: true })
},
async importAll() {
WIKI.logger.info(`(STORAGE/DISK) Importing all content from local disk folder to the DB...`)
await commonDisk.importFromDisk({
fullPath: this.config.path,
moduleName: 'DISK'
})
WIKI.logger.info('(STORAGE/DISK) Import completed.')
}
}