Updating to handle prod vs dev apps and deletion of attachments, as well as handling it on update.
This commit is contained in:
parent
f1981220af
commit
c75cc47ad3
2 changed files with 45 additions and 9 deletions
|
@ -26,6 +26,7 @@ const {
|
||||||
getFromDesignDoc,
|
getFromDesignDoc,
|
||||||
getFromMemoryDoc,
|
getFromMemoryDoc,
|
||||||
} = require("../view/utils")
|
} = require("../view/utils")
|
||||||
|
const { cloneDeep } = require("lodash/fp")
|
||||||
|
|
||||||
const CALCULATION_TYPES = {
|
const CALCULATION_TYPES = {
|
||||||
SUM: "sum",
|
SUM: "sum",
|
||||||
|
@ -110,14 +111,14 @@ exports.patch = async ctx => {
|
||||||
const inputs = ctx.request.body
|
const inputs = ctx.request.body
|
||||||
const tableId = inputs.tableId
|
const tableId = inputs.tableId
|
||||||
const isUserTable = tableId === InternalTables.USER_METADATA
|
const isUserTable = tableId === InternalTables.USER_METADATA
|
||||||
let dbRow
|
let oldRow
|
||||||
try {
|
try {
|
||||||
dbRow = await db.get(inputs._id)
|
oldRow = await db.get(inputs._id)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isUserTable) {
|
if (isUserTable) {
|
||||||
// don't include the rev, it'll be the global rev
|
// don't include the rev, it'll be the global rev
|
||||||
// this time
|
// this time
|
||||||
dbRow = {
|
oldRow = {
|
||||||
_id: inputs._id,
|
_id: inputs._id,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -126,13 +127,14 @@ exports.patch = async ctx => {
|
||||||
}
|
}
|
||||||
let dbTable = await db.get(tableId)
|
let dbTable = await db.get(tableId)
|
||||||
// need to build up full patch fields before coerce
|
// need to build up full patch fields before coerce
|
||||||
|
let combinedRow = cloneDeep(oldRow)
|
||||||
for (let key of Object.keys(inputs)) {
|
for (let key of Object.keys(inputs)) {
|
||||||
if (!dbTable.schema[key]) continue
|
if (!dbTable.schema[key]) continue
|
||||||
dbRow[key] = inputs[key]
|
combinedRow[key] = inputs[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
// this returns the table and row incase they have been updated
|
// this returns the table and row incase they have been updated
|
||||||
let { table, row } = inputProcessing(ctx.user, dbTable, dbRow)
|
let { table, row } = inputProcessing(ctx.user, dbTable, combinedRow)
|
||||||
const validateResult = await validate({
|
const validateResult = await validate({
|
||||||
row,
|
row,
|
||||||
table,
|
table,
|
||||||
|
@ -150,6 +152,8 @@ exports.patch = async ctx => {
|
||||||
tableId: row.tableId,
|
tableId: row.tableId,
|
||||||
table,
|
table,
|
||||||
})
|
})
|
||||||
|
// check if any attachments removed
|
||||||
|
await cleanupAttachments(appId, table, { oldRow, row })
|
||||||
|
|
||||||
if (isUserTable) {
|
if (isUserTable) {
|
||||||
// the row has been updated, need to put it into the ctx
|
// the row has been updated, need to put it into the ctx
|
||||||
|
|
|
@ -5,6 +5,8 @@ const { attachmentsRelativeURL } = require("../index")
|
||||||
const { processFormulas } = require("./utils")
|
const { processFormulas } = require("./utils")
|
||||||
const { deleteFiles } = require("../../utilities/fileSystem/utilities")
|
const { deleteFiles } = require("../../utilities/fileSystem/utilities")
|
||||||
const { ObjectStoreBuckets } = require("../../constants")
|
const { ObjectStoreBuckets } = require("../../constants")
|
||||||
|
const { isProdAppID, getDeployedAppID, dbExists } = require("@budibase/auth/db")
|
||||||
|
const CouchDB = require("../../db")
|
||||||
|
|
||||||
const BASE_AUTO_ID = 1
|
const BASE_AUTO_ID = 1
|
||||||
|
|
||||||
|
@ -97,6 +99,23 @@ const TYPE_TRANSFORM_MAP = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the old state of the row and the new one after an update, this will
|
||||||
|
* find the keys that have been removed in the updated row.
|
||||||
|
*/
|
||||||
|
function getRemovedAttachmentKeys(oldRow, row, attachmentKey) {
|
||||||
|
if (!oldRow[attachmentKey]) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const oldKeys = oldRow[attachmentKey].map(attachment => attachment.key)
|
||||||
|
// no attachments in new row, all removed
|
||||||
|
if (!row[attachmentKey]) {
|
||||||
|
return oldKeys
|
||||||
|
}
|
||||||
|
const newKeys = row[attachmentKey].map(attachment => attachment.key)
|
||||||
|
return oldKeys.filter(key => newKeys.indexOf(key) === -1)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will update any auto columns that are found on the row/table with the correct information based on
|
* This will update any auto columns that are found on the row/table with the correct information based on
|
||||||
* time now and the current logged in user making the request.
|
* time now and the current logged in user making the request.
|
||||||
|
@ -281,10 +300,18 @@ exports.outputProcessing = async (
|
||||||
* @param {object} table The table from which a row is being removed.
|
* @param {object} table The table from which a row is being removed.
|
||||||
* @param {any} row optional - the row being removed.
|
* @param {any} row optional - the row being removed.
|
||||||
* @param {any} rows optional - if multiple rows being deleted can do this in bulk.
|
* @param {any} rows optional - if multiple rows being deleted can do this in bulk.
|
||||||
|
* @param {any} oldRow optional - if updating a row this will determine the difference.
|
||||||
* @return {Promise<void>} When all attachments have been removed this will return.
|
* @return {Promise<void>} When all attachments have been removed this will return.
|
||||||
*/
|
*/
|
||||||
exports.cleanupAttachments = async (appId, table, {row, rows}) => {
|
exports.cleanupAttachments = async (appId, table, { row, rows, oldRow }) => {
|
||||||
// TODO: check app ID version
|
if (!isProdAppID(appId)) {
|
||||||
|
const prodAppId = getDeployedAppID(appId)
|
||||||
|
// if prod exists, then don't allow deleting
|
||||||
|
const exists = await dbExists(CouchDB, prodAppId)
|
||||||
|
if (exists) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
let files = []
|
let files = []
|
||||||
function addFiles(row, key) {
|
function addFiles(row, key) {
|
||||||
if (row[key]) {
|
if (row[key]) {
|
||||||
|
@ -295,11 +322,16 @@ exports.cleanupAttachments = async (appId, table, {row, rows}) => {
|
||||||
if (schema.type !== FieldTypes.ATTACHMENT) {
|
if (schema.type !== FieldTypes.ATTACHMENT) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (row) {
|
// if updating, need to manage the differences
|
||||||
|
if (oldRow && row) {
|
||||||
|
files = files.concat(getRemovedAttachmentKeys(oldRow, row, key))
|
||||||
|
} else if (row) {
|
||||||
addFiles(row, key)
|
addFiles(row, key)
|
||||||
} else if (rows) {
|
} else if (rows) {
|
||||||
rows.forEach(row => addFiles(row, key))
|
rows.forEach(row => addFiles(row, key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (files.length > 0) {
|
||||||
return deleteFiles(ObjectStoreBuckets.APPS, files)
|
return deleteFiles(ObjectStoreBuckets.APPS, files)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue