Getting downloading working correctly, some minor UI updates, adding a new middleware for converting a query string to a body (useful for when a GET has to be used).
This commit is contained in:
parent
34f03a5129
commit
01076bd35f
|
@ -0,0 +1,22 @@
|
|||
import { Ctx } from "@budibase/types"
|
||||
|
||||
/**
|
||||
* Expects a standard "query" query string property which is the JSON body
|
||||
* of the request, which has to be sent via query string due to the requirement
|
||||
* of making an endpoint a GET request e.g. downloading a file stream.
|
||||
*/
|
||||
export default function (ctx: Ctx, next: any) {
|
||||
const queryString = ctx.request.query?.query as string | undefined
|
||||
if (!queryString) {
|
||||
return next()
|
||||
}
|
||||
const decoded = decodeURIComponent(queryString)
|
||||
let json
|
||||
try {
|
||||
json = JSON.parse(decoded)
|
||||
} catch (err) {
|
||||
return next()
|
||||
}
|
||||
ctx.request.body = json
|
||||
return next()
|
||||
}
|
|
@ -17,4 +17,5 @@ export { default as builderOrAdmin } from "./builderOrAdmin"
|
|||
export { default as builderOnly } from "./builderOnly"
|
||||
export { default as logging } from "./logging"
|
||||
export { default as errorHandling } from "./errorHandling"
|
||||
export { default as downloadBody } from "./downloadBody"
|
||||
export * as joiValidator from "./joi-validator"
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
import UserRenderer from "./_components/UserRenderer.svelte"
|
||||
import TimeRenderer from "./_components/TimeRenderer.svelte"
|
||||
import AppColumnRenderer from "./_components/AppColumnRenderer.svelte"
|
||||
import download from "downloadjs"
|
||||
import { cloneDeep } from "lodash"
|
||||
|
||||
const schema = {
|
||||
date: { width: "0.8fr" },
|
||||
user: { width: "0.5fr" },
|
||||
app: { width: "1fr", fieldName: "name" },
|
||||
name: { width: "1fr" },
|
||||
app: { width: "0.75fr", fieldName: "name" },
|
||||
name: { width: "1.5fr" },
|
||||
view: { width: "auto", borderLeft: true, displayName: "" },
|
||||
}
|
||||
|
||||
|
@ -134,8 +134,7 @@
|
|||
$auditLogs.logs.bookmark
|
||||
)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
notifications.error("Error getting audit logs")
|
||||
notifications.error(`Error getting audit logs - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,24 +163,13 @@
|
|||
}
|
||||
|
||||
const viewDetails = detail => {
|
||||
console.log(detail)
|
||||
selectedLog = detail
|
||||
sidePanelVisible = true
|
||||
}
|
||||
async function exportView() {
|
||||
try {
|
||||
const data = await API.exportView({
|
||||
viewName: view,
|
||||
format: exportFormat,
|
||||
})
|
||||
} catch (error) {
|
||||
notifications.error(`Unable to export ${exportFormat.toUpperCase()} data`)
|
||||
}
|
||||
}
|
||||
|
||||
const downloadLogs = async () => {
|
||||
try {
|
||||
let response = await auditLogs.downloadLogs({
|
||||
window.location = auditLogs.getDownloadUrl({
|
||||
startDate,
|
||||
endDate,
|
||||
fullSearch: logSearchTerm,
|
||||
|
@ -189,8 +177,6 @@
|
|||
appIds: selectedApps,
|
||||
events: selectedEvents,
|
||||
})
|
||||
|
||||
// DO SOMETHING HERE???????????
|
||||
} catch (error) {
|
||||
notifications.error(`Error downloading logs: ` + error.message)
|
||||
}
|
||||
|
@ -205,6 +191,20 @@
|
|||
notifications.success("Copied")
|
||||
}
|
||||
|
||||
function cleanupMetadata(log) {
|
||||
const cloned = cloneDeep(log)
|
||||
cloned.userId = cloned.user._id
|
||||
if (cloned.app) {
|
||||
cloned.appId = cloned.app.appId
|
||||
}
|
||||
// remove props that are confused/not returned in download
|
||||
delete cloned._id
|
||||
delete cloned._rev
|
||||
delete cloned.app
|
||||
delete cloned.user
|
||||
return cloned
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
await auditLogs.getEventDefinitions()
|
||||
await licensing.init()
|
||||
|
@ -277,15 +277,15 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="max-width: 150px; ">
|
||||
<Search placeholder="Search" bind:value={logSearchTerm} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => downloadLogs()}
|
||||
style="padding-bottom: var(--spacing-s)"
|
||||
>
|
||||
<Icon name="Download" />
|
||||
</div>
|
||||
|
||||
<div style="max-width: 150px; ">
|
||||
<Search placeholder="Search" bind:value={logSearchTerm} />
|
||||
<Icon name="Download" hoverable />
|
||||
</div>
|
||||
</div>
|
||||
<Layout noPadding>
|
||||
|
@ -352,7 +352,7 @@
|
|||
disabled
|
||||
minHeight={"300px"}
|
||||
height={"100%"}
|
||||
value={JSON.stringify(selectedLog.metadata, null, 2)}
|
||||
value={JSON.stringify(cleanupMetadata(selectedLog), null, 2)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -28,15 +28,15 @@ export function createAuditLogsStore() {
|
|||
})
|
||||
}
|
||||
|
||||
async function downloadLogs(opts = {}) {
|
||||
return await API.downloadLogs(opts)
|
||||
function getDownloadUrl(opts = {}) {
|
||||
return API.getDownloadUrl(opts)
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
search,
|
||||
getEventDefinitions,
|
||||
downloadLogs,
|
||||
getDownloadUrl,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ const buildOpts = ({
|
|||
events,
|
||||
}) => {
|
||||
const opts = {}
|
||||
|
||||
|
||||
if (bookmark) {
|
||||
opts.bookmark = bookmark
|
||||
}
|
||||
|
@ -56,10 +56,8 @@ export const buildAuditLogsEndpoints = API => ({
|
|||
})
|
||||
},
|
||||
|
||||
downloadLogs: async opts => {
|
||||
return await API.post({
|
||||
url: `/api/global/auditlogs/download`,
|
||||
body: buildOpts(opts),
|
||||
})
|
||||
getDownloadUrl: opts => {
|
||||
const query = encodeURIComponent(JSON.stringify(opts))
|
||||
return `/api/global/auditlogs/download?query=${query}`
|
||||
},
|
||||
})
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import { mocks } from "@budibase/backend-core/tests"
|
||||
|
||||
mocks.licenses.useEnvironmentVariables()
|
||||
|
||||
describe("/api/global/auditlogs", () => {})
|
Loading…
Reference in New Issue