1
0
Fork 0
mirror of synced 2024-07-15 03:05:57 +12:00

Updating all of the route files to typescript, as well as some controllers.

This commit is contained in:
mike12345567 2022-11-22 18:49:19 +00:00
parent 92210144ff
commit 8c2d9ebec8
59 changed files with 748 additions and 639 deletions

View file

@ -2,8 +2,9 @@ import { DocumentType } from "../../db/utils"
import { Plugin } from "@budibase/types" import { Plugin } from "@budibase/types"
import { db as dbCore, context, tenancy } from "@budibase/backend-core" import { db as dbCore, context, tenancy } from "@budibase/backend-core"
import { getComponentLibraryManifest } from "../../utilities/fileSystem" import { getComponentLibraryManifest } from "../../utilities/fileSystem"
import { BBContext } from "@budibase/types"
exports.fetchAppComponentDefinitions = async function (ctx: any) { export async function fetchAppComponentDefinitions(ctx: BBContext) {
try { try {
const db = context.getAppDB() const db = context.getAppDB()
const app = await db.get(DocumentType.APP_METADATA) const app = await db.get(DocumentType.APP_METADATA)

View file

@ -1,15 +1,20 @@
const newid = require("../../../db/newid") import newid from "../../../db/newid"
const { getAppId } = require("@budibase/backend-core/context") import { context } from "@budibase/backend-core"
/** /**
* This is used to pass around information about the deployment that is occurring * This is used to pass around information about the deployment that is occurring
*/ */
class Deployment { export class Deployment {
_id: string
verification: any
status?: string
err?: any
constructor(id = null) { constructor(id = null) {
this._id = id || newid() this._id = id || newid()
} }
setVerification(verification) { setVerification(verification: any) {
if (!verification) { if (!verification) {
return return
} }
@ -20,14 +25,14 @@ class Deployment {
return this.verification return this.verification
} }
setStatus(status, err = null) { setStatus(status: string, err?: any) {
this.status = status this.status = status
if (err) { if (err) {
this.err = err this.err = err
} }
} }
fromJSON(json) { fromJSON(json: any) {
if (json.verification) { if (json.verification) {
this.setVerification(json.verification) this.setVerification(json.verification)
} }
@ -37,9 +42,9 @@ class Deployment {
} }
getJSON() { getJSON() {
const obj = { const obj: any = {
_id: this._id, _id: this._id,
appId: getAppId(), appId: context.getAppId(),
status: this.status, status: this.status,
} }
if (this.err) { if (this.err) {
@ -51,5 +56,3 @@ class Deployment {
return obj return obj
} }
} }
module.exports = Deployment

View file

@ -1,6 +1,5 @@
import { npmUpload, urlUpload, githubUpload, fileUpload } from "./uploaders" import { npmUpload, urlUpload, githubUpload, fileUpload } from "./uploaders"
import { getGlobalDB } from "@budibase/backend-core/tenancy" import { plugins as pluginCore, tenancy } from "@budibase/backend-core"
import { validate } from "@budibase/backend-core/plugins"
import { PluginType, FileType, PluginSource } from "@budibase/types" import { PluginType, FileType, PluginSource } from "@budibase/types"
import env from "../../../environment" import env from "../../../environment"
import { ClientAppSocket } from "../../../websocket" import { ClientAppSocket } from "../../../websocket"
@ -8,7 +7,7 @@ import { db as dbCore } from "@budibase/backend-core"
import { plugins } from "@budibase/pro" import { plugins } from "@budibase/pro"
export async function getPlugins(type?: PluginType) { export async function getPlugins(type?: PluginType) {
const db = getGlobalDB() const db = tenancy.getGlobalDB()
const response = await db.allDocs( const response = await db.allDocs(
dbCore.getPluginParams(null, { dbCore.getPluginParams(null, {
include_docs: true, include_docs: true,
@ -76,7 +75,7 @@ export async function create(ctx: any) {
break break
} }
validate(metadata?.schema) pluginCore.validate(metadata?.schema)
// Only allow components in cloud // Only allow components in cloud
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) { if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
@ -121,7 +120,7 @@ export async function processUploadedPlugin(
source?: PluginSource source?: PluginSource
) { ) {
const { metadata, directory } = await fileUpload(plugin) const { metadata, directory } = await fileUpload(plugin)
validate(metadata?.schema) pluginCore.validate(metadata?.schema)
// Only allow components in cloud // Only allow components in cloud
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) { if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {

View file

@ -27,12 +27,8 @@ import { breakExternalTableId, isSQL } from "../../../integrations/utils"
import { processObjectSync } from "@budibase/string-templates" import { processObjectSync } from "@budibase/string-templates"
// @ts-ignore // @ts-ignore
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { import { processFormulas, processDates } from "../../../utilities/rowProcessor"
processFormulas, import { context } from "@budibase/backend-core"
processDates,
} from "../../../utilities/rowProcessor/utils"
// @ts-ignore
import { getAppDB } from "@budibase/backend-core/context"
interface ManyRelationship { interface ManyRelationship {
tableId?: string tableId?: string
@ -444,7 +440,7 @@ module External {
// Process some additional data types // Process some additional data types
let finalRowArray = Object.values(finalRows) let finalRowArray = Object.values(finalRows)
finalRowArray = processDates(table, finalRowArray) finalRowArray = processDates(table, finalRowArray)
finalRowArray = processFormulas(table, finalRowArray) finalRowArray = processFormulas(table, finalRowArray) as Row[]
return finalRowArray.map((row: Row) => return finalRowArray.map((row: Row) =>
this.squashRelationshipColumns(table, row, relationships) this.squashRelationshipColumns(table, row, relationships)
@ -673,7 +669,7 @@ module External {
throw "Unable to run without a table name" throw "Unable to run without a table name"
} }
if (!this.datasource) { if (!this.datasource) {
const db = getAppDB() const db = context.getAppDB()
this.datasource = await db.get(datasourceId) this.datasource = await db.get(datasourceId)
if (!this.datasource || !this.datasource.entities) { if (!this.datasource || !this.datasource.entities) {
throw "No tables found, fetch tables before query." throw "No tables found, fetch tables before query."

View file

@ -1,15 +1,35 @@
const { SearchIndexes } = require("../../../db/utils") import { SearchIndexes } from "../../../db/utils"
const { removeKeyNumbering } = require("./utils") import { removeKeyNumbering } from "./utils"
const fetch = require("node-fetch") import fetch from "node-fetch"
const { getCouchInfo } = require("@budibase/backend-core/db") import { db as dbCore, context } from "@budibase/backend-core"
const { getAppId } = require("@budibase/backend-core/context") import { SearchFilters, Row } from "@budibase/types"
type SearchParams = {
tableId: string
sort?: string
sortOrder?: string
sortType?: string
limit?: number
bookmark?: string
version?: string
rows?: Row[]
}
/** /**
* Class to build lucene query URLs. * Class to build lucene query URLs.
* Optionally takes a base lucene query object. * Optionally takes a base lucene query object.
*/ */
class QueryBuilder { export class QueryBuilder {
constructor(base) { query: SearchFilters
limit: number
sort?: string
bookmark?: string
sortOrder: string
sortType: string
includeDocs: boolean
version?: string
constructor(base?: SearchFilters) {
this.query = { this.query = {
allOr: false, allOr: false,
string: {}, string: {},
@ -29,49 +49,52 @@ class QueryBuilder {
this.sortOrder = "ascending" this.sortOrder = "ascending"
this.sortType = "string" this.sortType = "string"
this.includeDocs = true this.includeDocs = true
this.version = null
} }
setVersion(version) { setVersion(version?: string) {
this.version = version if (version != null) {
this.version = version
}
return this return this
} }
setTable(tableId) { setTable(tableId: string) {
this.query.equal.tableId = tableId this.query.equal!.tableId = tableId
return this return this
} }
setLimit(limit) { setLimit(limit?: number) {
if (limit != null) { if (limit != null) {
this.limit = limit this.limit = limit
} }
return this return this
} }
setSort(sort) { setSort(sort?: string) {
if (sort != null) { if (sort != null) {
this.sort = sort this.sort = sort
} }
return this return this
} }
setSortOrder(sortOrder) { setSortOrder(sortOrder?: string) {
if (sortOrder != null) { if (sortOrder != null) {
this.sortOrder = sortOrder this.sortOrder = sortOrder
} }
return this return this
} }
setSortType(sortType) { setSortType(sortType?: string) {
if (sortType != null) { if (sortType != null) {
this.sortType = sortType this.sortType = sortType
} }
return this return this
} }
setBookmark(bookmark) { setBookmark(bookmark?: string) {
this.bookmark = bookmark if (bookmark != null) {
this.bookmark = bookmark
}
return this return this
} }
@ -80,61 +103,61 @@ class QueryBuilder {
return this return this
} }
addString(key, partial) { addString(key: string, partial: string) {
this.query.string[key] = partial this.query.string![key] = partial
return this return this
} }
addFuzzy(key, fuzzy) { addFuzzy(key: string, fuzzy: string) {
this.query.fuzzy[key] = fuzzy this.query.fuzzy![key] = fuzzy
return this return this
} }
addRange(key, low, high) { addRange(key: string, low: string | number, high: string | number) {
this.query.range = { this.query.range![key] = {
low, low,
high, high,
} }
return this return this
} }
addEqual(key, value) { addEqual(key: string, value: any) {
this.query.equal[key] = value this.query.equal![key] = value
return this return this
} }
addNotEqual(key, value) { addNotEqual(key: string, value: any) {
this.query.notEqual[key] = value this.query.notEqual![key] = value
return this return this
} }
addEmpty(key, value) { addEmpty(key: string, value: any) {
this.query.empty[key] = value this.query.empty![key] = value
return this return this
} }
addNotEmpty(key, value) { addNotEmpty(key: string, value: any) {
this.query.notEmpty[key] = value this.query.notEmpty![key] = value
return this return this
} }
addOneOf(key, value) { addOneOf(key: string, value: any) {
this.query.oneOf[key] = value this.query.oneOf![key] = value
return this return this
} }
addContains(key, value) { addContains(key: string, value: any) {
this.query.contains[key] = value this.query.contains![key] = value
return this return this
} }
addNotContains(key, value) { addNotContains(key: string, value: any) {
this.query.notContains[key] = value this.query.notContains![key] = value
return this return this
} }
addContainsAny(key, value) { addContainsAny(key: string, value: any) {
this.query.containsAny[key] = value this.query.containsAny![key] = value
return this return this
} }
@ -145,7 +168,7 @@ class QueryBuilder {
* @param options The preprocess options * @param options The preprocess options
* @returns {string|*} * @returns {string|*}
*/ */
preprocess(value, { escape, lowercase, wrap, type } = {}) { preprocess(value: any, { escape, lowercase, wrap, type }: any = {}) {
const hasVersion = !!this.version const hasVersion = !!this.version
// Determine if type needs wrapped // Determine if type needs wrapped
const originalType = typeof value const originalType = typeof value
@ -173,12 +196,12 @@ class QueryBuilder {
let query = allOr ? "" : "*:*" let query = allOr ? "" : "*:*"
const allPreProcessingOpts = { escape: true, lowercase: true, wrap: true } const allPreProcessingOpts = { escape: true, lowercase: true, wrap: true }
let tableId let tableId
if (this.query.equal.tableId) { if (this.query.equal!.tableId) {
tableId = this.query.equal.tableId tableId = this.query.equal!.tableId
delete this.query.equal.tableId delete this.query.equal!.tableId
} }
const equal = (key, value) => { const equal = (key: string, value: any) => {
// 0 evaluates to false, which means we would return all rows if we don't check it // 0 evaluates to false, which means we would return all rows if we don't check it
if (!value && value !== 0) { if (!value && value !== 0) {
return null return null
@ -186,7 +209,7 @@ class QueryBuilder {
return `${key}:${builder.preprocess(value, allPreProcessingOpts)}` return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
} }
const contains = (key, value, mode = "AND") => { const contains = (key: string, value: any, mode = "AND") => {
if (Array.isArray(value) && value.length === 0) { if (Array.isArray(value) && value.length === 0) {
return null return null
} }
@ -202,16 +225,17 @@ class QueryBuilder {
return `${key}:(${statement})` return `${key}:(${statement})`
} }
const notContains = (key, value) => { const notContains = (key: string, value: any) => {
// @ts-ignore
const allPrefix = allOr === "" ? "*:* AND" : "" const allPrefix = allOr === "" ? "*:* AND" : ""
return allPrefix + "NOT " + contains(key, value) return allPrefix + "NOT " + contains(key, value)
} }
const containsAny = (key, value) => { const containsAny = (key: string, value: any) => {
return contains(key, value, "OR") return contains(key, value, "OR")
} }
const oneOf = (key, value) => { const oneOf = (key: string, value: any) => {
if (!Array.isArray(value)) { if (!Array.isArray(value)) {
if (typeof value === "string") { if (typeof value === "string") {
value = value.split(",") value = value.split(",")
@ -229,7 +253,7 @@ class QueryBuilder {
return `${key}:(${orStatement})` return `${key}:(${orStatement})`
} }
function build(structure, queryFn) { function build(structure: any, queryFn: any) {
for (let [key, value] of Object.entries(structure)) { for (let [key, value] of Object.entries(structure)) {
// check for new format - remove numbering if needed // check for new format - remove numbering if needed
key = removeKeyNumbering(key) key = removeKeyNumbering(key)
@ -249,7 +273,7 @@ class QueryBuilder {
// Construct the actual lucene search query string from JSON structure // Construct the actual lucene search query string from JSON structure
if (this.query.string) { if (this.query.string) {
build(this.query.string, (key, value) => { build(this.query.string, (key: string, value: any) => {
if (!value) { if (!value) {
return null return null
} }
@ -262,7 +286,7 @@ class QueryBuilder {
}) })
} }
if (this.query.range) { if (this.query.range) {
build(this.query.range, (key, value) => { build(this.query.range, (key: string, value: any) => {
if (!value) { if (!value) {
return null return null
} }
@ -278,7 +302,7 @@ class QueryBuilder {
}) })
} }
if (this.query.fuzzy) { if (this.query.fuzzy) {
build(this.query.fuzzy, (key, value) => { build(this.query.fuzzy, (key: string, value: any) => {
if (!value) { if (!value) {
return null return null
} }
@ -294,7 +318,7 @@ class QueryBuilder {
build(this.query.equal, equal) build(this.query.equal, equal)
} }
if (this.query.notEqual) { if (this.query.notEqual) {
build(this.query.notEqual, (key, value) => { build(this.query.notEqual, (key: string, value: any) => {
if (!value) { if (!value) {
return null return null
} }
@ -302,10 +326,10 @@ class QueryBuilder {
}) })
} }
if (this.query.empty) { if (this.query.empty) {
build(this.query.empty, key => `!${key}:["" TO *]`) build(this.query.empty, (key: string) => `!${key}:["" TO *]`)
} }
if (this.query.notEmpty) { if (this.query.notEmpty) {
build(this.query.notEmpty, key => `${key}:["" TO *]`) build(this.query.notEmpty, (key: string) => `${key}:["" TO *]`)
} }
if (this.query.oneOf) { if (this.query.oneOf) {
build(this.query.oneOf, oneOf) build(this.query.oneOf, oneOf)
@ -329,7 +353,7 @@ class QueryBuilder {
} }
buildSearchBody() { buildSearchBody() {
let body = { let body: any = {
q: this.buildSearchQuery(), q: this.buildSearchQuery(),
limit: Math.min(this.limit, 200), limit: Math.min(this.limit, 200),
include_docs: this.includeDocs, include_docs: this.includeDocs,
@ -346,17 +370,14 @@ class QueryBuilder {
} }
async run() { async run() {
const appId = getAppId() const appId = context.getAppId()
const { url, cookie } = getCouchInfo() const { url, cookie } = dbCore.getCouchInfo()
const fullPath = `${url}/${appId}/_design/database/_search/${SearchIndexes.ROWS}` const fullPath = `${url}/${appId}/_design/database/_search/${SearchIndexes.ROWS}`
const body = this.buildSearchBody() const body = this.buildSearchBody()
return await runQuery(fullPath, body, cookie) return await runQuery(fullPath, body, cookie)
} }
} }
// exported for unit testing
exports.QueryBuilder = QueryBuilder
/** /**
* Executes a lucene search query. * Executes a lucene search query.
* @param url The query URL * @param url The query URL
@ -364,7 +385,7 @@ exports.QueryBuilder = QueryBuilder
* @param cookie The auth cookie for CouchDB * @param cookie The auth cookie for CouchDB
* @returns {Promise<{rows: []}>} * @returns {Promise<{rows: []}>}
*/ */
const runQuery = async (url, body, cookie) => { const runQuery = async (url: string, body: any, cookie: string) => {
const response = await fetch(url, { const response = await fetch(url, {
body: JSON.stringify(body), body: JSON.stringify(body),
method: "POST", method: "POST",
@ -374,11 +395,11 @@ const runQuery = async (url, body, cookie) => {
}) })
const json = await response.json() const json = await response.json()
let output = { let output: any = {
rows: [], rows: [],
} }
if (json.rows != null && json.rows.length > 0) { if (json.rows != null && json.rows.length > 0) {
output.rows = json.rows.map(row => row.doc) output.rows = json.rows.map((row: any) => row.doc)
} }
if (json.bookmark) { if (json.bookmark) {
output.bookmark = json.bookmark output.bookmark = json.bookmark
@ -402,7 +423,7 @@ const runQuery = async (url, body, cookie) => {
* rows {array|null} Current results in the recursive search * rows {array|null} Current results in the recursive search
* @returns {Promise<*[]|*>} * @returns {Promise<*[]|*>}
*/ */
const recursiveSearch = async (query, params) => { async function recursiveSearch(query: any, params: any): Promise<any> {
const bookmark = params.bookmark const bookmark = params.bookmark
const rows = params.rows || [] const rows = params.rows || []
if (rows.length >= params.limit) { if (rows.length >= params.limit) {
@ -450,7 +471,10 @@ const recursiveSearch = async (query, params) => {
* bookmark {string} The bookmark to resume from * bookmark {string} The bookmark to resume from
* @returns {Promise<{hasNextPage: boolean, rows: *[]}>} * @returns {Promise<{hasNextPage: boolean, rows: *[]}>}
*/ */
exports.paginatedSearch = async (query, params) => { export async function paginatedSearch(
query: SearchFilters,
params: SearchParams
) {
let limit = params.limit let limit = params.limit
if (limit == null || isNaN(limit) || limit < 0) { if (limit == null || isNaN(limit) || limit < 0) {
limit = 50 limit = 50
@ -496,7 +520,7 @@ exports.paginatedSearch = async (query, params) => {
* limit {number} The desired number of results * limit {number} The desired number of results
* @returns {Promise<{rows: *}>} * @returns {Promise<{rows: *}>}
*/ */
exports.fullSearch = async (query, params) => { export async function fullSearch(query: SearchFilters, params: SearchParams) {
let limit = params.limit let limit = params.limit
if (limit == null || isNaN(limit) || limit < 0) { if (limit == null || isNaN(limit) || limit < 0) {
limit = 1000 limit = 1000

View file

@ -1,13 +1,14 @@
const { getRowParams } = require("../../../db/utils") import { getRowParams } from "../../../db/utils"
const { import {
outputProcessing, outputProcessing,
processAutoColumn, processAutoColumn,
processFormulas, processFormulas,
} = require("../../../utilities/rowProcessor") } from "../../../utilities/rowProcessor"
const { FieldTypes, FormulaTypes } = require("../../../constants") import { FieldTypes, FormulaTypes } from "../../../constants"
import { context } from "@budibase/backend-core"
import { Table, Row } from "@budibase/types"
const { isEqual } = require("lodash") const { isEqual } = require("lodash")
const { cloneDeep } = require("lodash/fp") const { cloneDeep } = require("lodash/fp")
const { getAppDB } = require("@budibase/backend-core/context")
/** /**
* This function runs through a list of enriched rows, looks at the rows which * This function runs through a list of enriched rows, looks at the rows which
@ -15,22 +16,22 @@ const { getAppDB } = require("@budibase/backend-core/context")
* updated. * updated.
* NOTE: this will only for affect static formulas. * NOTE: this will only for affect static formulas.
*/ */
exports.updateRelatedFormula = async (table, enrichedRows) => { exports.updateRelatedFormula = async (table: Table, enrichedRows: Row[]) => {
const db = getAppDB() const db = context.getAppDB()
// no formula to update, we're done // no formula to update, we're done
if (!table.relatedFormula) { if (!table.relatedFormula) {
return return
} }
let promises = [] let promises: Promise<any>[] = []
for (let enrichedRow of Array.isArray(enrichedRows) for (let enrichedRow of Array.isArray(enrichedRows)
? enrichedRows ? enrichedRows
: [enrichedRows]) { : [enrichedRows]) {
// the related rows by tableId // the related rows by tableId
let relatedRows = {} let relatedRows: Record<string, Row[]> = {}
for (let [key, field] of Object.entries(enrichedRow)) { for (let [key, field] of Object.entries(enrichedRow)) {
const columnDefinition = table.schema[key] const columnDefinition = table.schema[key]
if (columnDefinition && columnDefinition.type === FieldTypes.LINK) { if (columnDefinition && columnDefinition.type === FieldTypes.LINK) {
const relatedTableId = columnDefinition.tableId const relatedTableId = columnDefinition.tableId!
if (!relatedRows[relatedTableId]) { if (!relatedRows[relatedTableId]) {
relatedRows[relatedTableId] = [] relatedRows[relatedTableId] = []
} }
@ -38,7 +39,7 @@ exports.updateRelatedFormula = async (table, enrichedRows) => {
} }
} }
for (let tableId of table.relatedFormula) { for (let tableId of table.relatedFormula) {
let relatedTable let relatedTable: Table
try { try {
// no rows to update, skip // no rows to update, skip
if (!relatedRows[tableId] || relatedRows[tableId].length === 0) { if (!relatedRows[tableId] || relatedRows[tableId].length === 0) {
@ -48,7 +49,7 @@ exports.updateRelatedFormula = async (table, enrichedRows) => {
} catch (err) { } catch (err) {
// no error scenario, table doesn't seem to exist anymore, ignore // no error scenario, table doesn't seem to exist anymore, ignore
} }
for (let column of Object.values(relatedTable.schema)) { for (let column of Object.values(relatedTable!.schema)) {
// needs updated in related rows // needs updated in related rows
if ( if (
column.type === FieldTypes.FORMULA && column.type === FieldTypes.FORMULA &&
@ -57,7 +58,7 @@ exports.updateRelatedFormula = async (table, enrichedRows) => {
// re-enrich rows for all the related, don't update the related formula for them // re-enrich rows for all the related, don't update the related formula for them
promises = promises.concat( promises = promises.concat(
relatedRows[tableId].map(related => relatedRows[tableId].map(related =>
exports.finaliseRow(relatedTable, related, { finaliseRow(relatedTable, related, {
updateFormula: false, updateFormula: false,
}) })
) )
@ -70,8 +71,8 @@ exports.updateRelatedFormula = async (table, enrichedRows) => {
await Promise.all(promises) await Promise.all(promises)
} }
exports.updateAllFormulasInTable = async table => { export async function updateAllFormulasInTable(table: Table) {
const db = getAppDB() const db = context.getAppDB()
// start by getting the raw rows (which will be written back to DB after update) // start by getting the raw rows (which will be written back to DB after update)
let rows = ( let rows = (
await db.allDocs( await db.allDocs(
@ -88,7 +89,9 @@ exports.updateAllFormulasInTable = async table => {
const updatedRows = [] const updatedRows = []
for (let row of rows) { for (let row of rows) {
// find the enriched row, if found process the formulas // find the enriched row, if found process the formulas
const enrichedRow = enrichedRows.find(enriched => enriched._id === row._id) const enrichedRow = enrichedRows.find(
(enriched: any) => enriched._id === row._id
)
if (enrichedRow) { if (enrichedRow) {
const processed = processFormulas(table, cloneDeep(row), { const processed = processFormulas(table, cloneDeep(row), {
dynamic: false, dynamic: false,
@ -109,12 +112,14 @@ exports.updateAllFormulasInTable = async table => {
* row. The reason we need to return the enriched row is that the automation row created trigger * row. The reason we need to return the enriched row is that the automation row created trigger
* expects the row to be totally enriched/contain all relationships. * expects the row to be totally enriched/contain all relationships.
*/ */
exports.finaliseRow = async ( export async function finaliseRow(
table, table: Table,
row, row: Row,
{ oldTable, updateFormula } = { updateFormula: true } { oldTable, updateFormula }: { oldTable?: Table; updateFormula: boolean } = {
) => { updateFormula: true,
const db = getAppDB() }
) {
const db = context.getAppDB()
row.type = "row" row.type = "row"
// process the row before return, to include relationships // process the row before return, to include relationships
let enrichedRow = await outputProcessing(table, cloneDeep(row), { let enrichedRow = await outputProcessing(table, cloneDeep(row), {
@ -131,7 +136,7 @@ exports.finaliseRow = async (
if (oldTable && !isEqual(oldTable, table)) { if (oldTable && !isEqual(oldTable, table)) {
try { try {
await db.put(table) await db.put(table)
} catch (err) { } catch (err: any) {
if (err.status === 409) { if (err.status === 409) {
const updatedTable = await db.get(table._id) const updatedTable = await db.get(table._id)
let response = processAutoColumn(null, updatedTable, row, { let response = processAutoColumn(null, updatedTable, row, {

View file

@ -1,33 +1,32 @@
import { InternalTables } from "../../../db/utils"
import userController from "../user"
import { FieldTypes } from "../../../constants"
import { context } from "@budibase/backend-core"
import { makeExternalQuery } from "../../../integrations/base/query"
import { BBContext, Row, Table } from "@budibase/types"
export { removeKeyNumbering } from "../../../integrations/base/utils"
const validateJs = require("validate.js") const validateJs = require("validate.js")
const { cloneDeep } = require("lodash/fp") const { cloneDeep } = require("lodash/fp")
const { InternalTables } = require("../../../db/utils")
const userController = require("../user")
const { FieldTypes } = require("../../../constants")
const { getAppDB } = require("@budibase/backend-core/context")
const { makeExternalQuery } = require("../../../integrations/base/query")
const { removeKeyNumbering } = require("../../../integrations/base/utils")
validateJs.extend(validateJs.validators.datetime, { validateJs.extend(validateJs.validators.datetime, {
parse: function (value) { parse: function (value: string) {
return new Date(value).getTime() return new Date(value).getTime()
}, },
// Input is a unix timestamp // Input is a unix timestamp
format: function (value) { format: function (value: string) {
return new Date(value).toISOString() return new Date(value).toISOString()
}, },
}) })
exports.removeKeyNumbering = removeKeyNumbering export async function getDatasourceAndQuery(json: any) {
exports.getDatasourceAndQuery = async json => {
const datasourceId = json.endpoint.datasourceId const datasourceId = json.endpoint.datasourceId
const db = getAppDB() const db = context.getAppDB()
const datasource = await db.get(datasourceId) const datasource = await db.get(datasourceId)
return makeExternalQuery(datasource, json) return makeExternalQuery(datasource, json)
} }
exports.findRow = async (ctx, tableId, rowId) => { export async function findRow(ctx: BBContext, tableId: string, rowId: string) {
const db = getAppDB() const db = context.getAppDB()
let row let row
// TODO remove special user case in future // TODO remove special user case in future
if (tableId === InternalTables.USER_METADATA) { if (tableId === InternalTables.USER_METADATA) {
@ -45,12 +44,20 @@ exports.findRow = async (ctx, tableId, rowId) => {
return row return row
} }
exports.validate = async ({ tableId, row, table }) => { export async function validate({
tableId,
row,
table,
}: {
tableId?: string
row: Row
table: Table
}) {
if (!table) { if (!table) {
const db = getAppDB() const db = context.getAppDB()
table = await db.get(tableId) table = await db.get(tableId)
} }
const errors = {} const errors: any = {}
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
const constraints = cloneDeep(table.schema[fieldName].constraints) const constraints = cloneDeep(table.schema[fieldName].constraints)
const type = table.schema[fieldName].type const type = table.schema[fieldName].type
@ -70,7 +77,7 @@ exports.validate = async ({ tableId, row, table }) => {
if (!Array.isArray(row[fieldName])) { if (!Array.isArray(row[fieldName])) {
row[fieldName] = row[fieldName].split(",") row[fieldName] = row[fieldName].split(",")
} }
row[fieldName].map(val => { row[fieldName].map((val: any) => {
if ( if (
!constraints.inclusion.includes(val) && !constraints.inclusion.includes(val) &&
constraints.inclusion.length !== 0 constraints.inclusion.length !== 0

View file

@ -7,9 +7,9 @@ import {
roles, roles,
} from "@budibase/backend-core" } from "@budibase/backend-core"
import { updateAppPackage } from "./application" import { updateAppPackage } from "./application"
import { Plugin, ScreenProps } from "@budibase/types" import { Plugin, ScreenProps, BBContext } from "@budibase/types"
exports.fetch = async (ctx: any) => { export async function fetch(ctx: BBContext) {
const db = context.getAppDB() const db = context.getAppDB()
const screens = ( const screens = (
@ -20,13 +20,17 @@ exports.fetch = async (ctx: any) => {
) )
).rows.map((el: any) => el.doc) ).rows.map((el: any) => el.doc)
const roleId = ctx.user?.role?._id as string
if (!roleId) {
ctx.throw("Unable to retrieve users role ID.")
}
ctx.body = await new roles.AccessController().checkScreensAccess( ctx.body = await new roles.AccessController().checkScreensAccess(
screens, screens,
ctx.user.role._id roleId
) )
} }
exports.save = async (ctx: any) => { export async function save(ctx: BBContext) {
const db = context.getAppDB() const db = context.getAppDB()
let screen = ctx.request.body let screen = ctx.request.body
@ -92,7 +96,7 @@ exports.save = async (ctx: any) => {
} }
} }
exports.destroy = async (ctx: any) => { export async function destroy(ctx: BBContext) {
const db = context.getAppDB() const db = context.getAppDB()
const id = ctx.params.screenId const id = ctx.params.screenId
const screen = await db.get(id) const screen = await db.get(id)
@ -106,7 +110,7 @@ exports.destroy = async (ctx: any) => {
ctx.status = 200 ctx.status = 200
} }
const findPlugins = (component: ScreenProps, foundPlugins: string[]) => { function findPlugins(component: ScreenProps, foundPlugins: string[]) {
if (!component) { if (!component) {
return return
} }

View file

@ -1,11 +0,0 @@
const ScriptRunner = require("../../utilities/scriptRunner")
exports.execute = async function (ctx) {
const { script, context } = ctx.request.body
const runner = new ScriptRunner(script, context)
ctx.body = runner.execute()
}
exports.save = async function (ctx) {
ctx.throw(501, "Not currently implemented")
}

View file

@ -0,0 +1,12 @@
import ScriptRunner from "../../utilities/scriptRunner"
import { BBContext } from "@budibase/types"
export async function execute(ctx: BBContext) {
const { script, context } = ctx.request.body
const runner = new ScriptRunner(script, context)
ctx.body = runner.execute()
}
export async function save(ctx: BBContext) {
ctx.throw(501, "Not currently implemented")
}

View file

@ -1,17 +1,20 @@
const fetch = require("node-fetch") import nodeFetch from "node-fetch"
const { downloadTemplate } = require("../../utilities/fileSystem") import { downloadTemplate as dlTemplate } from "../../utilities/fileSystem"
const env = require("../../environment") import env from "../../environment"
import { BBContext } from "@budibase/types"
// development flag, can be used to test against templates exported locally // development flag, can be used to test against templates exported locally
const DEFAULT_TEMPLATES_BUCKET = const DEFAULT_TEMPLATES_BUCKET =
"prod-budi-templates.s3-eu-west-1.amazonaws.com" "prod-budi-templates.s3-eu-west-1.amazonaws.com"
exports.fetch = async function (ctx) { export async function fetch(ctx: BBContext) {
let type = env.TEMPLATE_REPOSITORY let type = env.TEMPLATE_REPOSITORY
let response, let response,
error = false error = false
try { try {
response = await fetch(`https://${DEFAULT_TEMPLATES_BUCKET}/manifest.json`) response = await nodeFetch(
`https://${DEFAULT_TEMPLATES_BUCKET}/manifest.json`
)
if (response.status !== 200) { if (response.status !== 200) {
error = true error = true
} }
@ -29,10 +32,10 @@ exports.fetch = async function (ctx) {
// can't currently test this, have to ignore from coverage // can't currently test this, have to ignore from coverage
/* istanbul ignore next */ /* istanbul ignore next */
exports.downloadTemplate = async function (ctx) { export async function downloadTemplate(ctx: BBContext) {
const { type, name } = ctx.params const { type, name } = ctx.params
await downloadTemplate(type, name) await dlTemplate(type, name)
ctx.body = { ctx.body = {
message: `template ${type}:${name} downloaded successfully.`, message: `template ${type}:${name} downloaded successfully.`,

View file

@ -1,9 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/analytics")
const router = new Router()
router.get("/api/bbtel", controller.isEnabled)
router.post("/api/bbtel/ping", controller.ping)
module.exports = router

View file

@ -0,0 +1,9 @@
import Router from "@koa/router"
import * as controller from "../controllers/analytics"
const router: Router = new Router()
router.get("/api/bbtel", controller.isEnabled)
router.post("/api/bbtel/ping", controller.ping)
export = router

View file

@ -1,12 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/apikeys")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
router
.get("/api/keys", authorized(BUILDER), controller.fetch)
.put("/api/keys/:key", authorized(BUILDER), controller.update)
module.exports = router

View file

@ -0,0 +1,12 @@
import Router from "@koa/router"
import * as controller from "../controllers/apikeys"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
router
.get("/api/keys", authorized(permissions.BUILDER), controller.fetch)
.put("/api/keys/:key", authorized(permissions.BUILDER), controller.update)
export = router

View file

@ -1,16 +1,20 @@
import Router from "@koa/router" import Router from "@koa/router"
import * as controller from "../controllers/application" import * as controller from "../controllers/application"
import authorized from "../../middleware/authorized" import authorized from "../../middleware/authorized"
import { BUILDER } from "@budibase/backend-core/permissions" import { permissions } from "@budibase/backend-core"
import { applicationValidator } from "./utils/validators" import { applicationValidator } from "./utils/validators"
const router: Router = new Router() const router: Router = new Router()
router router
.post("/api/applications/:appId/sync", authorized(BUILDER), controller.sync) .post(
"/api/applications/:appId/sync",
authorized(permissions.BUILDER),
controller.sync
)
.post( .post(
"/api/applications", "/api/applications",
authorized(BUILDER), authorized(permissions.BUILDER),
applicationValidator(), applicationValidator(),
controller.create controller.create
) )
@ -19,20 +23,24 @@ router
.get("/api/applications/:appId/appPackage", controller.fetchAppPackage) .get("/api/applications/:appId/appPackage", controller.fetchAppPackage)
.put( .put(
"/api/applications/:appId", "/api/applications/:appId",
authorized(BUILDER), authorized(permissions.BUILDER),
applicationValidator({ isCreate: false }), applicationValidator({ isCreate: false }),
controller.update controller.update
) )
.post( .post(
"/api/applications/:appId/client/update", "/api/applications/:appId/client/update",
authorized(BUILDER), authorized(permissions.BUILDER),
controller.updateClient controller.updateClient
) )
.post( .post(
"/api/applications/:appId/client/revert", "/api/applications/:appId/client/revert",
authorized(BUILDER), authorized(permissions.BUILDER),
controller.revertClient controller.revertClient
) )
.delete("/api/applications/:appId", authorized(BUILDER), controller.destroy) .delete(
"/api/applications/:appId",
authorized(permissions.BUILDER),
controller.destroy
)
export default router export = router

View file

@ -5,4 +5,4 @@ const router: Router = new Router()
router.get("/api/self", controller.fetchSelf) router.get("/api/self", controller.fetchSelf)
export default router export = router

View file

@ -1,85 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/automation")
const authorized = require("../../middleware/authorized")
const {
BUILDER,
PermissionLevel,
PermissionType,
} = require("@budibase/backend-core/permissions")
const { bodyResource, paramResource } = require("../../middleware/resourceId")
const {
middleware: appInfoMiddleware,
AppType,
} = require("../../middleware/appInfo")
const { automationValidator } = require("./utils/validators")
const router = new Router()
router
.get(
"/api/automations/trigger/list",
authorized(BUILDER),
controller.getTriggerList
)
.get(
"/api/automations/action/list",
authorized(BUILDER),
controller.getActionList
)
.get(
"/api/automations/definitions/list",
authorized(BUILDER),
controller.getDefinitionList
)
.get("/api/automations", authorized(BUILDER), controller.fetch)
.get(
"/api/automations/:id",
paramResource("id"),
authorized(BUILDER),
controller.find
)
.put(
"/api/automations",
bodyResource("_id"),
authorized(BUILDER),
automationValidator(true),
controller.update
)
.post(
"/api/automations",
authorized(BUILDER),
automationValidator(false),
controller.create
)
.post(
"/api/automations/logs/search",
authorized(BUILDER),
controller.logSearch
)
.delete(
"/api/automations/logs",
authorized(BUILDER),
controller.clearLogError
)
.delete(
"/api/automations/:id/:rev",
paramResource("id"),
authorized(BUILDER),
controller.destroy
)
.post(
"/api/automations/:id/trigger",
appInfoMiddleware({ appType: AppType.PROD }),
paramResource("id"),
authorized(PermissionType.AUTOMATION, PermissionLevel.EXECUTE),
controller.trigger
)
.post(
"/api/automations/:id/test",
appInfoMiddleware({ appType: AppType.DEV }),
paramResource("id"),
authorized(PermissionType.AUTOMATION, PermissionLevel.EXECUTE),
controller.test
)
module.exports = router

View file

@ -0,0 +1,87 @@
import Router from "@koa/router"
import * as controller from "../controllers/automation"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import { bodyResource, paramResource } from "../../middleware/resourceId"
import {
middleware as appInfoMiddleware,
AppType,
} from "../../middleware/appInfo"
import { automationValidator } from "./utils/validators"
const router: Router = new Router()
router
.get(
"/api/automations/trigger/list",
authorized(permissions.BUILDER),
controller.getTriggerList
)
.get(
"/api/automations/action/list",
authorized(permissions.BUILDER),
controller.getActionList
)
.get(
"/api/automations/definitions/list",
authorized(permissions.BUILDER),
controller.getDefinitionList
)
.get("/api/automations", authorized(permissions.BUILDER), controller.fetch)
.get(
"/api/automations/:id",
paramResource("id"),
authorized(permissions.BUILDER),
controller.find
)
.put(
"/api/automations",
bodyResource("_id"),
authorized(permissions.BUILDER),
automationValidator(true),
controller.update
)
.post(
"/api/automations",
authorized(permissions.BUILDER),
automationValidator(false),
controller.create
)
.post(
"/api/automations/logs/search",
authorized(permissions.BUILDER),
controller.logSearch
)
.delete(
"/api/automations/logs",
authorized(permissions.BUILDER),
controller.clearLogError
)
.delete(
"/api/automations/:id/:rev",
paramResource("id"),
authorized(permissions.BUILDER),
controller.destroy
)
.post(
"/api/automations/:id/trigger",
appInfoMiddleware({ appType: AppType.PROD }),
paramResource("id"),
authorized(
permissions.PermissionType.AUTOMATION,
permissions.PermissionLevel.EXECUTE
),
controller.trigger
)
.post(
"/api/automations/:id/test",
appInfoMiddleware({ appType: AppType.DEV }),
paramResource("id"),
authorized(
permissions.PermissionType.AUTOMATION,
permissions.PermissionLevel.EXECUTE
),
controller.test
)
export = router

View file

@ -1,10 +1,14 @@
import Router from "@koa/router" import Router from "@koa/router"
import * as controller from "../controllers/backup" import * as controller from "../controllers/backup"
import authorized from "../../middleware/authorized" import authorized from "../../middleware/authorized"
import { BUILDER } from "@budibase/backend-core/permissions" import { permissions } from "@budibase/backend-core"
const router: Router = new Router() const router: Router = new Router()
router.get("/api/backups/export", authorized(BUILDER), controller.exportAppDump) router.get(
"/api/backups/export",
authorized(permissions.BUILDER),
controller.exportAppDump
)
export default router export = router

View file

@ -1,14 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/cloud")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
router
.get("/api/cloud/export", authorized(BUILDER), controller.exportApps)
// has to be public, only run if apps don't exist
.post("/api/cloud/import", controller.importApps)
.get("/api/cloud/import/complete", controller.hasBeenImported)
module.exports = router

View file

@ -0,0 +1,18 @@
import Router from "@koa/router"
import * as controller from "../controllers/cloud"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
router
.get(
"/api/cloud/export",
authorized(permissions.BUILDER),
controller.exportApps
)
// has to be public, only run if apps don't exist
.post("/api/cloud/import", controller.importApps)
.get("/api/cloud/import/complete", controller.hasBeenImported)
export = router

View file

@ -1,14 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/component")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
router.get(
"/api/:appId/components/definitions",
authorized(BUILDER),
controller.fetchAppComponentDefinitions
)
module.exports = router

View file

@ -0,0 +1,14 @@
import Router from "@koa/router"
import * as controller from "../controllers/component"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
router.get(
"/api/:appId/components/definitions",
authorized(permissions.BUILDER),
controller.fetchAppComponentDefinitions
)
export = router

View file

@ -1,51 +0,0 @@
const Router = require("@koa/router")
const datasourceController = require("../controllers/datasource")
const authorized = require("../../middleware/authorized")
const {
BUILDER,
PermissionLevel,
PermissionType,
} = require("@budibase/backend-core/permissions")
const {
datasourceValidator,
datasourceQueryValidator,
} = require("./utils/validators")
const router = new Router()
router
.get("/api/datasources", authorized(BUILDER), datasourceController.fetch)
.get(
"/api/datasources/:datasourceId",
authorized(PermissionType.TABLE, PermissionLevel.READ),
datasourceController.find
)
.put(
"/api/datasources/:datasourceId",
authorized(PermissionType.TABLE, PermissionLevel.READ),
datasourceController.update
)
.post(
"/api/datasources/query",
authorized(PermissionType.TABLE, PermissionLevel.READ),
datasourceQueryValidator(),
datasourceController.query
)
.post(
"/api/datasources/:datasourceId/schema",
authorized(BUILDER),
datasourceController.buildSchemaFromDb
)
.post(
"/api/datasources",
authorized(BUILDER),
datasourceValidator(),
datasourceController.save
)
.delete(
"/api/datasources/:datasourceId/:revId",
authorized(BUILDER),
datasourceController.destroy
)
module.exports = router

View file

@ -0,0 +1,60 @@
import Router from "@koa/router"
import * as datasourceController from "../controllers/datasource"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import {
datasourceValidator,
datasourceQueryValidator,
} from "./utils/validators"
const router: Router = new Router()
router
.get(
"/api/datasources",
authorized(permissions.BUILDER),
datasourceController.fetch
)
.get(
"/api/datasources/:datasourceId",
authorized(
permissions.PermissionType.TABLE,
permissions.PermissionLevel.READ
),
datasourceController.find
)
.put(
"/api/datasources/:datasourceId",
authorized(
permissions.PermissionType.TABLE,
permissions.PermissionLevel.READ
),
datasourceController.update
)
.post(
"/api/datasources/query",
authorized(
permissions.PermissionType.TABLE,
permissions.PermissionLevel.READ
),
datasourceQueryValidator(),
datasourceController.query
)
.post(
"/api/datasources/:datasourceId/schema",
authorized(permissions.BUILDER),
datasourceController.buildSchemaFromDb
)
.post(
"/api/datasources",
authorized(permissions.BUILDER),
datasourceValidator(),
datasourceController.save
)
.delete(
"/api/datasources/:datasourceId/:revId",
authorized(permissions.BUILDER),
datasourceController.destroy
)
export = router

View file

@ -18,4 +18,4 @@ router
) )
.post("/api/deploy", authorized(permissions.BUILDER), controller.deployApp) .post("/api/deploy", authorized(permissions.BUILDER), controller.deployApp)
export default router export = router

View file

@ -1,26 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/dev")
const env = require("../../environment")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
function redirectPath(path) {
router
.get(`/api/${path}/:devPath(.*)`, controller.buildRedirectGet(path))
.post(`/api/${path}/:devPath(.*)`, controller.buildRedirectPost(path))
.delete(`/api/${path}/:devPath(.*)`, controller.buildRedirectDelete(path))
}
if (env.isDev() || env.isTest()) {
redirectPath("global")
redirectPath("system")
}
router
.get("/api/dev/version", authorized(BUILDER), controller.getBudibaseVersion)
.delete("/api/dev/:appId/lock", authorized(BUILDER), controller.clearLock)
.post("/api/dev/:appId/revert", authorized(BUILDER), controller.revert)
module.exports = router

View file

@ -0,0 +1,38 @@
import Router from "@koa/router"
import * as controller from "../controllers/dev"
import env from "../../environment"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
function redirectPath(path: string) {
router
.get(`/api/${path}/:devPath(.*)`, controller.buildRedirectGet(path))
.post(`/api/${path}/:devPath(.*)`, controller.buildRedirectPost(path))
.delete(`/api/${path}/:devPath(.*)`, controller.buildRedirectDelete(path))
}
if (env.isDev() || env.isTest()) {
redirectPath("global")
redirectPath("system")
}
router
.get(
"/api/dev/version",
authorized(permissions.BUILDER),
controller.getBudibaseVersion
)
.delete(
"/api/dev/:appId/lock",
authorized(permissions.BUILDER),
controller.clearLock
)
.post(
"/api/dev/:appId/revert",
authorized(permissions.BUILDER),
controller.revert
)
export = router

View file

@ -1,12 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/integration")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
router
.get("/api/integrations", authorized(BUILDER), controller.fetch)
.get("/api/integrations/:type", authorized(BUILDER), controller.find)
module.exports = router

View file

@ -0,0 +1,16 @@
import Router from "@koa/router"
import controller from "../controllers/integration"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
router
.get("/api/integrations", authorized(permissions.BUILDER), controller.fetch)
.get(
"/api/integrations/:type",
authorized(permissions.BUILDER),
controller.find
)
export = router

View file

@ -1,16 +0,0 @@
const Router = require("@koa/router")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const controller = require("../controllers/layout")
const router = new Router()
router
.post("/api/layouts", authorized(BUILDER), controller.save)
.delete(
"/api/layouts/:layoutId/:layoutRev",
authorized(BUILDER),
controller.destroy
)
module.exports = router

View file

@ -0,0 +1,16 @@
import Router from "@koa/router"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import controller from "../controllers/layout"
const router: Router = new Router()
router
.post("/api/layouts", authorized(permissions.BUILDER), controller.save)
.delete(
"/api/layouts/:layoutId/:layoutRev",
authorized(permissions.BUILDER),
controller.destroy
)
export = router

View file

@ -1,38 +1,38 @@
const Router = require("@koa/router") import Router from "@koa/router"
const controller = require("../controllers/metadata") import * as controller from "../controllers/metadata"
const { import {
middleware: appInfoMiddleware, middleware as appInfoMiddleware,
AppType, AppType,
} = require("../../middleware/appInfo") } from "../../middleware/appInfo"
const authorized = require("../../middleware/authorized") import authorized from "../../middleware/authorized"
const { BUILDER } = require("@budibase/backend-core/permissions") import { permissions } from "@budibase/backend-core"
const router = new Router() const router: Router = new Router()
router router
.post( .post(
"/api/metadata/:type/:entityId", "/api/metadata/:type/:entityId",
authorized(BUILDER), authorized(permissions.BUILDER),
appInfoMiddleware({ appType: AppType.DEV }), appInfoMiddleware({ appType: AppType.DEV }),
controller.saveMetadata controller.saveMetadata
) )
.delete( .delete(
"/api/metadata/:type/:entityId", "/api/metadata/:type/:entityId",
authorized(BUILDER), authorized(permissions.BUILDER),
appInfoMiddleware({ appType: AppType.DEV }), appInfoMiddleware({ appType: AppType.DEV }),
controller.deleteMetadata controller.deleteMetadata
) )
.get( .get(
"/api/metadata/type", "/api/metadata/type",
authorized(BUILDER), authorized(permissions.BUILDER),
appInfoMiddleware({ appType: AppType.DEV }), appInfoMiddleware({ appType: AppType.DEV }),
controller.getTypes controller.getTypes
) )
.get( .get(
"/api/metadata/:type/:entityId", "/api/metadata/:type/:entityId",
authorized(BUILDER), authorized(permissions.BUILDER),
appInfoMiddleware({ appType: AppType.DEV }), appInfoMiddleware({ appType: AppType.DEV }),
controller.getMetadata controller.getMetadata
) )
module.exports = router export = router

View file

@ -1,14 +0,0 @@
const Router = require("@koa/router")
const migrationsController = require("../controllers/migrations")
const router = new Router()
const { internalApi } = require("@budibase/backend-core/auth")
router
.post("/api/migrations/run", internalApi, migrationsController.migrate)
.get(
"/api/migrations/definitions",
internalApi,
migrationsController.fetchDefinitions
)
module.exports = router

View file

@ -0,0 +1,14 @@
import Router from "@koa/router"
import * as migrationsController from "../controllers/migrations"
import { auth } from "@budibase/backend-core"
const router: Router = new Router()
router
.post("/api/migrations/run", auth.internalApi, migrationsController.migrate)
.get(
"/api/migrations/definitions",
auth.internalApi,
migrationsController.fetchDefinitions
)
export = router

View file

@ -1,33 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/permission")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const { permissionValidator } = require("./utils/validators")
const router = new Router()
router
.get("/api/permission/builtin", authorized(BUILDER), controller.fetchBuiltin)
.get("/api/permission/levels", authorized(BUILDER), controller.fetchLevels)
.get("/api/permission", authorized(BUILDER), controller.fetch)
.get(
"/api/permission/:resourceId",
authorized(BUILDER),
controller.getResourcePerms
)
// adding a specific role/level for the resource overrides the underlying access control
.post(
"/api/permission/:roleId/:resourceId/:level",
authorized(BUILDER),
permissionValidator(),
controller.addPermission
)
// deleting the level defaults it back the underlying access control for the resource
.delete(
"/api/permission/:roleId/:resourceId/:level",
authorized(BUILDER),
permissionValidator(),
controller.removePermission
)
module.exports = router

View file

@ -0,0 +1,41 @@
import Router from "@koa/router"
import * as controller from "../controllers/permission"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import { permissionValidator } from "./utils/validators"
const router: Router = new Router()
router
.get(
"/api/permission/builtin",
authorized(permissions.BUILDER),
controller.fetchBuiltin
)
.get(
"/api/permission/levels",
authorized(permissions.BUILDER),
controller.fetchLevels
)
.get("/api/permission", authorized(permissions.BUILDER), controller.fetch)
.get(
"/api/permission/:resourceId",
authorized(permissions.BUILDER),
controller.getResourcePerms
)
// adding a specific role/level for the resource overrides the underlying access control
.post(
"/api/permission/:roleId/:resourceId/:level",
authorized(permissions.BUILDER),
permissionValidator(),
controller.addPermission
)
// deleting the level defaults it back the underlying access control for the resource
.delete(
"/api/permission/:roleId/:resourceId/:level",
authorized(permissions.BUILDER),
permissionValidator(),
controller.removePermission
)
export = router

View file

@ -1,14 +1,22 @@
import Router from "@koa/router" import Router from "@koa/router"
import * as controller from "../controllers/plugin" import * as controller from "../controllers/plugin"
import authorized from "../../middleware/authorized" import authorized from "../../middleware/authorized"
import { BUILDER } from "@budibase/backend-core/permissions" import { permissions } from "@budibase/backend-core"
const router: Router = new Router() const router: Router = new Router()
router router
.post("/api/plugin/upload", authorized(BUILDER), controller.upload) .post(
.post("/api/plugin", authorized(BUILDER), controller.create) "/api/plugin/upload",
.get("/api/plugin", authorized(BUILDER), controller.fetch) authorized(permissions.BUILDER),
.delete("/api/plugin/:pluginId", authorized(BUILDER), controller.destroy) controller.upload
)
.post("/api/plugin", authorized(permissions.BUILDER), controller.create)
.get("/api/plugin", authorized(permissions.BUILDER), controller.fetch)
.delete(
"/api/plugin/:pluginId",
authorized(permissions.BUILDER),
controller.destroy
)
export default router export default router

View file

@ -1,22 +1,19 @@
const Router = require("@koa/router") import Router from "@koa/router"
const queryController = require("../controllers/query") import * as queryController from "../controllers/query"
const authorized = require("../../middleware/authorized") import authorized from "../../middleware/authorized"
const { import { permissions } from "@budibase/backend-core"
PermissionLevel, import {
PermissionType,
BUILDER,
} = require("@budibase/backend-core/permissions")
const {
bodyResource, bodyResource,
bodySubResource, bodySubResource,
paramResource, paramResource,
} = require("../../middleware/resourceId") } from "../../middleware/resourceId"
const { import {
generateQueryPreviewValidation, generateQueryPreviewValidation,
generateQueryValidation, generateQueryValidation,
} = require("../controllers/query/validation") } from "../controllers/query/validation"
const { BUILDER, PermissionType, PermissionLevel } = permissions
const router = new Router() const router: Router = new Router()
router router
.get("/api/queries", authorized(BUILDER), queryController.fetch) .get("/api/queries", authorized(BUILDER), queryController.fetch)
@ -48,17 +45,17 @@ router
authorized(PermissionType.QUERY, PermissionLevel.WRITE), authorized(PermissionType.QUERY, PermissionLevel.WRITE),
queryController.executeV1 queryController.executeV1
) )
.post(
"/api/v2/queries/:queryId",
paramResource("queryId"),
authorized(PermissionType.QUERY, PermissionLevel.WRITE),
queryController.executeV2
)
.delete( .delete(
"/api/queries/:queryId/:revId", "/api/queries/:queryId/:revId",
paramResource("queryId"), paramResource("queryId"),
authorized(BUILDER), authorized(BUILDER),
queryController.destroy queryController.destroy
) )
.post(
"/api/v2/queries/:queryId",
paramResource("queryId"),
authorized(PermissionType.QUERY, PermissionLevel.WRITE),
queryController.executeV2 as any
)
module.exports = router export = router

View file

@ -1,15 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/role")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const { roleValidator } = require("./utils/validators")
const router = new Router()
router
.post("/api/roles", authorized(BUILDER), roleValidator(), controller.save)
.get("/api/roles", authorized(BUILDER), controller.fetch)
.get("/api/roles/:roleId", authorized(BUILDER), controller.find)
.delete("/api/roles/:roleId/:rev", authorized(BUILDER), controller.destroy)
module.exports = router

View file

@ -0,0 +1,24 @@
import Router from "@koa/router"
import * as controller from "../controllers/role"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import { roleValidator } from "./utils/validators"
const router: Router = new Router()
router
.post(
"/api/roles",
authorized(permissions.BUILDER),
roleValidator(),
controller.save
)
.get("/api/roles", authorized(permissions.BUILDER), controller.fetch)
.get("/api/roles/:roleId", authorized(permissions.BUILDER), controller.find)
.delete(
"/api/roles/:roleId/:rev",
authorized(permissions.BUILDER),
controller.destroy
)
export = router

View file

@ -1,14 +0,0 @@
const Router = require("@koa/router")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const controller = require("../controllers/routing")
const router = new Router()
router
// gets correct structure for user role
.get("/api/routing/client", controller.clientFetch)
// gets the full structure, not just the correct screen ID for user role
.get("/api/routing", authorized(BUILDER), controller.fetch)
module.exports = router

View file

@ -0,0 +1,14 @@
import Router from "@koa/router"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import * as controller from "../controllers/routing"
const router: Router = new Router()
router
// gets correct structure for user role
.get("/api/routing/client", controller.clientFetch)
// gets the full structure, not just the correct screen ID for user role
.get("/api/routing", authorized(permissions.BUILDER), controller.fetch)
export = router

View file

@ -2,11 +2,9 @@ import Router from "@koa/router"
import * as rowController from "../controllers/row" import * as rowController from "../controllers/row"
import authorized from "../../middleware/authorized" import authorized from "../../middleware/authorized"
import { paramResource, paramSubResource } from "../../middleware/resourceId" import { paramResource, paramSubResource } from "../../middleware/resourceId"
const { import { permissions } from "@budibase/backend-core"
PermissionLevel,
PermissionType,
} = require("@budibase/backend-core/permissions")
const { internalSearchValidator } = require("./utils/validators") const { internalSearchValidator } = require("./utils/validators")
const { PermissionType, PermissionLevel } = permissions
const router: Router = new Router() const router: Router = new Router()

View file

@ -1,18 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/screen")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const { screenValidator } = require("./utils/validators")
const router = new Router()
router
.get("/api/screens", authorized(BUILDER), controller.fetch)
.post("/api/screens", authorized(BUILDER), screenValidator(), controller.save)
.delete(
"/api/screens/:screenId/:screenRev",
authorized(BUILDER),
controller.destroy
)
module.exports = router

View file

@ -0,0 +1,23 @@
import Router from "@koa/router"
import * as controller from "../controllers/screen"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
import { screenValidator } from "./utils/validators"
const router: Router = new Router()
router
.get("/api/screens", authorized(permissions.BUILDER), controller.fetch)
.post(
"/api/screens",
authorized(permissions.BUILDER),
screenValidator(),
controller.save
)
.delete(
"/api/screens/:screenId/:screenRev",
authorized(permissions.BUILDER),
controller.destroy
)
export = router

View file

@ -1,10 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/script")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
router.post("/api/script", authorized(BUILDER), controller.save)
module.exports = router

View file

@ -0,0 +1,10 @@
import Router from "@koa/router"
import * as controller from "../controllers/script"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core/permissions"
const router: Router = new Router()
router.post("/api/script", authorized(permissions.BUILDER), controller.save)
export = router

View file

@ -2,13 +2,10 @@ import Router from "@koa/router"
import * as controller from "../controllers/static" import * as controller from "../controllers/static"
import { budibaseTempDir } from "../../utilities/budibaseDir" import { budibaseTempDir } from "../../utilities/budibaseDir"
import authorized from "../../middleware/authorized" import authorized from "../../middleware/authorized"
import { import { permissions } from "@budibase/backend-core"
BUILDER,
PermissionType,
PermissionLevel,
} from "@budibase/backend-core/permissions"
import * as env from "../../environment" import * as env from "../../environment"
import { paramResource } from "../../middleware/resourceId" import { paramResource } from "../../middleware/resourceId"
const { BUILDER, PermissionType, PermissionLevel } = permissions
const router: Router = new Router() const router: Router = new Router()
@ -65,4 +62,4 @@ router
controller.getSignedUploadURL controller.getSignedUploadURL
) )
export default router export = router

View file

@ -1,15 +1,12 @@
const Router = require("@koa/router") import Router from "@koa/router"
const tableController = require("../controllers/table") import * as tableController from "../controllers/table"
const authorized = require("../../middleware/authorized") import authorized from "../../middleware/authorized"
const { paramResource, bodyResource } = require("../../middleware/resourceId") import { paramResource, bodyResource } from "../../middleware/resourceId"
const { import { permissions } from "@budibase/backend-core"
BUILDER, import { tableValidator } from "./utils/validators"
PermissionLevel, const { BUILDER, PermissionLevel, PermissionType } = permissions
PermissionType,
} = require("@budibase/backend-core/permissions")
const { tableValidator } = require("./utils/validators")
const router = new Router() const router: Router = new Router()
router router
/** /**
@ -193,4 +190,4 @@ router
tableController.bulkImport tableController.bulkImport
) )
module.exports = router export = router

View file

@ -1,16 +0,0 @@
const Router = require("@koa/router")
const controller = require("../controllers/templates")
const authorized = require("../../middleware/authorized")
const { BUILDER } = require("@budibase/backend-core/permissions")
const router = new Router()
router
.get("/api/templates", authorized(BUILDER), controller.fetch)
.get(
"/api/templates/:type/:name",
authorized(BUILDER),
controller.downloadTemplate
)
module.exports = router

View file

@ -0,0 +1,16 @@
import Router from "@koa/router"
import * as controller from "../controllers/templates"
import authorized from "../../middleware/authorized"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
router
.get("/api/templates", authorized(permissions.BUILDER), controller.fetch)
.get(
"/api/templates/:type/:name",
authorized(permissions.BUILDER),
controller.downloadTemplate
)
export = router

View file

@ -1,12 +1,10 @@
const Router = require("@koa/router") import Router from "@koa/router"
const controller = require("../controllers/user") import controller from "../controllers/user"
const authorized = require("../../middleware/authorized") import authorized from "../../middleware/authorized"
const { import { permissions } from "@budibase/backend-core"
PermissionLevel, const { PermissionType, PermissionLevel } = permissions
PermissionType,
} = require("@budibase/backend-core/permissions")
const router = new Router() const router: Router = new Router()
router router
.get( .get(
@ -50,4 +48,4 @@ router
controller.getFlags controller.getFlags
) )
module.exports = router export = router

View file

@ -1,31 +0,0 @@
const Router = require("@koa/router")
const viewController = require("../controllers/view")
const rowController = require("../controllers/row")
const authorized = require("../../middleware/authorized")
const { paramResource } = require("../../middleware/resourceId")
const {
BUILDER,
PermissionType,
PermissionLevel,
} = require("@budibase/backend-core/permissions")
const router = new Router()
router
.get("/api/views/export", authorized(BUILDER), viewController.exportView)
.get(
"/api/views/:viewName",
paramResource("viewName"),
authorized(PermissionType.VIEW, PermissionLevel.READ),
rowController.fetchView
)
.get("/api/views", authorized(BUILDER), viewController.fetch)
.delete(
"/api/views/:viewName",
paramResource("viewName"),
authorized(BUILDER),
viewController.destroy
)
.post("/api/views", authorized(BUILDER), viewController.save)
module.exports = router

View file

@ -0,0 +1,34 @@
import Router from "@koa/router"
import * as viewController from "../controllers/view"
import * as rowController from "../controllers/row"
import authorized from "../../middleware/authorized"
import { paramResource } from "../../middleware/resourceId"
import { permissions } from "@budibase/backend-core"
const router: Router = new Router()
router
.get(
"/api/views/export",
authorized(permissions.BUILDER),
viewController.exportView
)
.get(
"/api/views/:viewName",
paramResource("viewName"),
authorized(
permissions.PermissionType.VIEW,
permissions.PermissionLevel.READ
),
rowController.fetchView
)
.get("/api/views", authorized(permissions.BUILDER), viewController.fetch)
.delete(
"/api/views/:viewName",
paramResource("viewName"),
authorized(permissions.BUILDER),
viewController.destroy
)
.post("/api/views", authorized(permissions.BUILDER), viewController.save)
export = router

View file

@ -24,4 +24,4 @@ router
// this shouldn't have authorisation, right now its always public // this shouldn't have authorisation, right now its always public
.post("/api/webhooks/trigger/:instance/:id", controller.trigger) .post("/api/webhooks/trigger/:instance/:id", controller.trigger)
export default router export = router

View file

@ -49,7 +49,7 @@ function getRemovedAttachmentKeys(
* for automatic ID purposes. * for automatic ID purposes.
*/ */
export function processAutoColumn( export function processAutoColumn(
user: User, user: User | null,
table: Table, table: Table,
row: Row, row: Row,
opts: AutoColumnProcessingOpts opts: AutoColumnProcessingOpts
@ -71,7 +71,7 @@ export function processAutoColumn(
} }
switch (schema.subtype) { switch (schema.subtype) {
case AutoFieldSubTypes.CREATED_BY: case AutoFieldSubTypes.CREATED_BY:
if (creating && shouldUpdateUserFields) { if (creating && shouldUpdateUserFields && user) {
row[key] = [user.userId] row[key] = [user.userId]
} }
break break
@ -81,7 +81,7 @@ export function processAutoColumn(
} }
break break
case AutoFieldSubTypes.UPDATED_BY: case AutoFieldSubTypes.UPDATED_BY:
if (shouldUpdateUserFields) { if (shouldUpdateUserFields && user) {
row[key] = [user.userId] row[key] = [user.userId]
} }
break break

View file

@ -35,13 +35,16 @@ export function fixAutoColumnSubType(column: FieldSchema) {
*/ */
export function processFormulas( export function processFormulas(
table: Table, table: Table,
rows: Row[], rows: Row[] | Row,
{ dynamic, contextRows }: any = { dynamic: true } { dynamic, contextRows }: any = { dynamic: true }
) { ) {
const single = !Array.isArray(rows) const single = !Array.isArray(rows)
let rowArray: Row[]
if (single) { if (single) {
rows = [rows] rowArray = [rows]
contextRows = contextRows ? [contextRows] : contextRows contextRows = contextRows ? [contextRows] : contextRows
} else {
rowArray = rows
} }
for (let [column, schema] of Object.entries(table.schema)) { for (let [column, schema] of Object.entries(table.schema)) {
const isStatic = schema.formulaType === FormulaTypes.STATIC const isStatic = schema.formulaType === FormulaTypes.STATIC
@ -53,18 +56,18 @@ export function processFormulas(
continue continue
} }
// iterate through rows and process formula // iterate through rows and process formula
for (let i = 0; i < rows.length; i++) { for (let i = 0; i < rowArray.length; i++) {
if (schema.formula) { if (schema.formula) {
let row = rows[i] let row = rowArray[i]
let context = contextRows ? contextRows[i] : row let context = contextRows ? contextRows[i] : row
rows[i] = { rowArray[i] = {
...row, ...row,
[column]: processStringSync(schema.formula, context), [column]: processStringSync(schema.formula, context),
} }
} }
} }
} }
return single ? rows[0] : rows return single ? rowArray[0] : rowArray
} }
/** /**