Merge branch 'master' of github.com:Budibase/budibase into budi-8608-ai-platform-level-config-pt-2
This commit is contained in:
commit
7fc0f38296
|
@ -117,9 +117,9 @@ jobs:
|
|||
- name: Test
|
||||
run: |
|
||||
if ${{ env.ONLY_AFFECTED_TASKS }}; then
|
||||
yarn test --ignore=@budibase/worker --ignore=@budibase/server --ignore @budibase/account-portal-server --since=${{ env.NX_BASE_BRANCH }}
|
||||
yarn test --ignore=@budibase/worker --ignore=@budibase/server --since=${{ env.NX_BASE_BRANCH }}
|
||||
else
|
||||
yarn test --ignore=@budibase/worker --ignore=@budibase/server --ignore @budibase/account-portal-server
|
||||
yarn test --ignore=@budibase/worker --ignore=@budibase/server
|
||||
fi
|
||||
|
||||
test-worker:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"version": "2.32.0",
|
||||
"version": "2.32.4",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*",
|
||||
|
|
|
@ -117,7 +117,10 @@
|
|||
"axios": "1.6.3",
|
||||
"xml2js": "0.6.2",
|
||||
"unset-value": "2.0.1",
|
||||
"passport": "0.6.0"
|
||||
"passport": "0.6.0",
|
||||
"fast-xml-parser": "4.4.1",
|
||||
"@azure/identity": "4.2.1",
|
||||
"kind-of": "6.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0 <21.0.0"
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7899d07904d89d48954dd500da7b5dec32b781dd
|
||||
Subproject commit 905773d70854a43c6ef2461c7a49671bff56fedc
|
|
@ -7,8 +7,9 @@ import {
|
|||
doWithDB,
|
||||
} from "../db"
|
||||
import { getAppDB } from "../context"
|
||||
import { Screen, Role as RoleDoc } from "@budibase/types"
|
||||
import { Screen, Role as RoleDoc, RoleUIMetadata } from "@budibase/types"
|
||||
import cloneDeep from "lodash/fp/cloneDeep"
|
||||
import { RoleColor } from "@budibase/shared-core"
|
||||
|
||||
export const BUILTIN_ROLE_IDS = {
|
||||
ADMIN: "ADMIN",
|
||||
|
@ -44,11 +45,18 @@ export class Role implements RoleDoc {
|
|||
permissionId: string
|
||||
inherits?: string
|
||||
version?: string
|
||||
permissions = {}
|
||||
permissions: Record<string, PermissionLevel[]> = {}
|
||||
uiMetadata?: RoleUIMetadata
|
||||
|
||||
constructor(id: string, name: string, permissionId: string) {
|
||||
constructor(
|
||||
id: string,
|
||||
name: string,
|
||||
permissionId: string,
|
||||
uiMetadata?: RoleUIMetadata
|
||||
) {
|
||||
this._id = id
|
||||
this.name = name
|
||||
this.uiMetadata = uiMetadata
|
||||
this.permissionId = permissionId
|
||||
// version for managing the ID - removing the role_ when responding
|
||||
this.version = RoleIDVersion.NAME
|
||||
|
@ -63,21 +71,54 @@ export class Role implements RoleDoc {
|
|||
const BUILTIN_ROLES = {
|
||||
ADMIN: new Role(
|
||||
BUILTIN_IDS.ADMIN,
|
||||
"Admin",
|
||||
BuiltinPermissionID.ADMIN
|
||||
BUILTIN_IDS.ADMIN,
|
||||
BuiltinPermissionID.ADMIN,
|
||||
{
|
||||
displayName: "App admin",
|
||||
description: "Can do everything",
|
||||
color: RoleColor.ADMIN,
|
||||
}
|
||||
).addInheritance(BUILTIN_IDS.POWER),
|
||||
POWER: new Role(
|
||||
BUILTIN_IDS.POWER,
|
||||
"Power",
|
||||
BuiltinPermissionID.POWER
|
||||
BUILTIN_IDS.POWER,
|
||||
BuiltinPermissionID.POWER,
|
||||
{
|
||||
displayName: "App power user",
|
||||
description: "An app user with more access",
|
||||
color: RoleColor.POWER,
|
||||
}
|
||||
).addInheritance(BUILTIN_IDS.BASIC),
|
||||
BASIC: new Role(
|
||||
BUILTIN_IDS.BASIC,
|
||||
"Basic",
|
||||
BuiltinPermissionID.WRITE
|
||||
BUILTIN_IDS.BASIC,
|
||||
BuiltinPermissionID.WRITE,
|
||||
{
|
||||
displayName: "App user",
|
||||
description: "Any logged in user",
|
||||
color: RoleColor.BASIC,
|
||||
}
|
||||
).addInheritance(BUILTIN_IDS.PUBLIC),
|
||||
PUBLIC: new Role(BUILTIN_IDS.PUBLIC, "Public", BuiltinPermissionID.PUBLIC),
|
||||
BUILDER: new Role(BUILTIN_IDS.BUILDER, "Builder", BuiltinPermissionID.ADMIN),
|
||||
PUBLIC: new Role(
|
||||
BUILTIN_IDS.PUBLIC,
|
||||
BUILTIN_IDS.PUBLIC,
|
||||
BuiltinPermissionID.PUBLIC,
|
||||
{
|
||||
displayName: "Public user",
|
||||
description: "Accessible to anyone",
|
||||
color: RoleColor.PUBLIC,
|
||||
}
|
||||
),
|
||||
BUILDER: new Role(
|
||||
BUILTIN_IDS.BUILDER,
|
||||
BUILTIN_IDS.BUILDER,
|
||||
BuiltinPermissionID.ADMIN,
|
||||
{
|
||||
displayName: "Builder user",
|
||||
description: "Users that can edit this app",
|
||||
color: RoleColor.BUILDER,
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
export function getBuiltinRoles(): { [key: string]: RoleDoc } {
|
||||
|
@ -244,9 +285,9 @@ export async function getUserRoleHierarchy(
|
|||
// some templates/older apps will use a simple string instead of array for roles
|
||||
// convert the string to an array using the theory that write is higher than read
|
||||
export function checkForRoleResourceArray(
|
||||
rolePerms: { [key: string]: string[] },
|
||||
rolePerms: Record<string, PermissionLevel[]>,
|
||||
resourceId: string
|
||||
) {
|
||||
): Record<string, PermissionLevel[]> {
|
||||
if (rolePerms && !Array.isArray(rolePerms[resourceId])) {
|
||||
const permLevel = rolePerms[resourceId] as any
|
||||
rolePerms[resourceId] = [permLevel]
|
||||
|
|
|
@ -102,10 +102,6 @@ export const useAppBuilders = () => {
|
|||
return useFeature(Feature.APP_BUILDERS)
|
||||
}
|
||||
|
||||
export const useViewPermissions = () => {
|
||||
return useFeature(Feature.VIEW_PERMISSIONS)
|
||||
}
|
||||
|
||||
export const useViewReadonlyColumns = () => {
|
||||
return useFeature(Feature.VIEW_READONLY_COLUMNS)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
const dispatch = createEventDispatcher()
|
||||
const RemoveID = "remove"
|
||||
const subType = $licensing.license.plan.type ?? null
|
||||
|
||||
$: enrichLabel = label => (labelPrefix ? `${labelPrefix} ${label}` : label)
|
||||
$: options = getOptions(
|
||||
|
@ -68,13 +69,13 @@
|
|||
}))
|
||||
|
||||
// Add creator if required
|
||||
if (allowCreator) {
|
||||
if (allowCreator || isEnterprisePlan(subType)) {
|
||||
options.unshift({
|
||||
_id: Constants.Roles.CREATOR,
|
||||
name: "Can edit",
|
||||
tag:
|
||||
!$licensing.perAppBuildersEnabled &&
|
||||
capitalise(Constants.PlanType.BUSINESS),
|
||||
tag: isEnterprisePlan(subType)
|
||||
? null
|
||||
: capitalise(Constants.PlanType.ENTERPRISE),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -117,6 +118,14 @@
|
|||
dispatch("change", e.detail)
|
||||
}
|
||||
}
|
||||
|
||||
function isEnterprisePlan(subType) {
|
||||
return (
|
||||
subType === Constants.PlanType.ENTERPRISE ||
|
||||
subType === Constants.PlanType.ENTERPRISE_BASIC ||
|
||||
subType === Constants.PlanType.ENTERPRISE_BASIC_TRIAL
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if fancySelect}
|
||||
|
@ -134,9 +143,12 @@
|
|||
getOptionValue={role => role._id}
|
||||
getOptionColour={getColor}
|
||||
getOptionIcon={getIcon}
|
||||
isOptionEnabled={option =>
|
||||
option._id !== Constants.Roles.CREATOR ||
|
||||
$licensing.perAppBuildersEnabled}
|
||||
isOptionEnabled={option => {
|
||||
if (option._id === Constants.Roles.CREATOR) {
|
||||
return isEnterprisePlan(subType)
|
||||
}
|
||||
return true
|
||||
}}
|
||||
{placeholder}
|
||||
{error}
|
||||
/>
|
||||
|
@ -154,10 +166,12 @@
|
|||
getOptionValue={role => role._id}
|
||||
getOptionColour={getColor}
|
||||
getOptionIcon={getIcon}
|
||||
isOptionEnabled={option =>
|
||||
(option._id !== Constants.Roles.CREATOR ||
|
||||
$licensing.perAppBuildersEnabled) &&
|
||||
option.enabled !== false}
|
||||
isOptionEnabled={option => {
|
||||
if (option._id === Constants.Roles.CREATOR) {
|
||||
return isEnterprisePlan(subType)
|
||||
}
|
||||
return option.enabled !== false
|
||||
}}
|
||||
{placeholder}
|
||||
{error}
|
||||
/>
|
||||
|
|
|
@ -85,6 +85,7 @@ export const PlanType = {
|
|||
TEAM: "team",
|
||||
PRO: "pro",
|
||||
BUSINESS: "business",
|
||||
PREMIUM: "premium",
|
||||
ENTERPRISE: "enterprise",
|
||||
ENTERPRISE_BASIC_TRIAL: "enterprise_basic_trial",
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ec1d2bda756f02c6b4efdee086e4c59b0c2a1b0c
|
||||
Subproject commit 922431260e90d558a1ca55398475412e75088057
|
|
@ -63,7 +63,7 @@
|
|||
"@koa/router": "8.0.8",
|
||||
"@socket.io/redis-adapter": "^8.2.1",
|
||||
"@types/xml2js": "^0.4.14",
|
||||
"airtable": "0.10.1",
|
||||
"airtable": "0.12.2",
|
||||
"arangojs": "7.2.0",
|
||||
"archiver": "7.0.1",
|
||||
"aws-sdk": "2.1030.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { permissions, roles, context, HTTPError } from "@budibase/backend-core"
|
||||
import { permissions, roles, context } from "@budibase/backend-core"
|
||||
import {
|
||||
UserCtx,
|
||||
Database,
|
||||
|
@ -45,18 +45,6 @@ async function updatePermissionOnRole(
|
|||
}: { roleId: string; resourceId: string; level: PermissionLevel },
|
||||
updateType: PermissionUpdateType
|
||||
) {
|
||||
const allowedAction = await sdk.permissions.resourceActionAllowed({
|
||||
resourceId,
|
||||
level,
|
||||
})
|
||||
|
||||
if (!allowedAction.allowed) {
|
||||
throw new HTTPError(
|
||||
`You are not allowed to '${allowedAction.level}' the resource type '${allowedAction.resourceType}'`,
|
||||
403
|
||||
)
|
||||
}
|
||||
|
||||
const db = context.getAppDB()
|
||||
const remove = updateType === PermissionUpdateType.REMOVE
|
||||
const isABuiltin = roles.isBuiltin(roleId)
|
||||
|
@ -75,7 +63,9 @@ async function updatePermissionOnRole(
|
|||
// resource from another role and then adding to the new role
|
||||
for (let role of dbRoles) {
|
||||
let updated = false
|
||||
const rolePermissions = role.permissions ? role.permissions : {}
|
||||
const rolePermissions: Record<string, PermissionLevel[]> = role.permissions
|
||||
? role.permissions
|
||||
: {}
|
||||
// make sure its an array, also handle migrating
|
||||
if (
|
||||
!rolePermissions[resourceId] ||
|
||||
|
@ -83,7 +73,7 @@ async function updatePermissionOnRole(
|
|||
) {
|
||||
rolePermissions[resourceId] =
|
||||
typeof rolePermissions[resourceId] === "string"
|
||||
? [rolePermissions[resourceId] as unknown as string]
|
||||
? [rolePermissions[resourceId] as unknown as PermissionLevel]
|
||||
: []
|
||||
}
|
||||
// handle the removal/updating the role which has this permission first
|
||||
|
@ -182,9 +172,6 @@ export async function getResourcePerms(
|
|||
},
|
||||
{} as Record<string, ResourcePermissionInfo>
|
||||
),
|
||||
requiresPlanToModify: (
|
||||
await sdk.permissions.allowsExplicitPermissions(resourceId)
|
||||
).minPlan,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ import {
|
|||
SaveRoleResponse,
|
||||
UserCtx,
|
||||
UserMetadata,
|
||||
UserRoles,
|
||||
DocumentType,
|
||||
} from "@budibase/types"
|
||||
import { sdk as sharedSdk } from "@budibase/shared-core"
|
||||
import { RoleColor, sdk as sharedSdk } from "@budibase/shared-core"
|
||||
import sdk from "../../sdk"
|
||||
|
||||
const UpdateRolesOptions = {
|
||||
|
@ -62,7 +62,8 @@ export async function find(ctx: UserCtx<void, FindRoleResponse>) {
|
|||
|
||||
export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
||||
const db = context.getAppDB()
|
||||
let { _id, name, inherits, permissionId, version } = ctx.request.body
|
||||
let { _id, name, inherits, permissionId, version, uiMetadata } =
|
||||
ctx.request.body
|
||||
let isCreate = false
|
||||
const isNewVersion = version === roles.RoleIDVersion.NAME
|
||||
|
||||
|
@ -80,17 +81,25 @@ export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
|||
_id = dbCore.prefixRoleID(_id)
|
||||
}
|
||||
|
||||
let dbRole
|
||||
if (!isCreate) {
|
||||
dbRole = await db.get<UserRoles>(_id)
|
||||
let dbRole: Role | undefined
|
||||
if (!isCreate && _id?.startsWith(DocumentType.ROLE)) {
|
||||
dbRole = await db.get<Role>(_id)
|
||||
}
|
||||
if (dbRole && dbRole.name !== name && isNewVersion) {
|
||||
ctx.throw(400, "Cannot change custom role name")
|
||||
}
|
||||
|
||||
const role = new roles.Role(_id, name, permissionId).addInheritance(inherits)
|
||||
if (ctx.request.body._rev) {
|
||||
role._rev = ctx.request.body._rev
|
||||
const role = new roles.Role(_id, name, permissionId, {
|
||||
displayName: uiMetadata?.displayName || name,
|
||||
description: uiMetadata?.description || "Custom role",
|
||||
color: uiMetadata?.color || RoleColor.DEFAULT_CUSTOM,
|
||||
}).addInheritance(inherits)
|
||||
if (dbRole?.permissions && !role.permissions) {
|
||||
role.permissions = dbRole.permissions
|
||||
}
|
||||
const foundRev = ctx.request.body._rev || dbRole?._rev
|
||||
if (foundRev) {
|
||||
role._rev = foundRev
|
||||
}
|
||||
const result = await db.put(role)
|
||||
if (isCreate) {
|
||||
|
|
|
@ -1,20 +1,5 @@
|
|||
const mockedSdk = sdk.permissions as jest.Mocked<typeof sdk.permissions>
|
||||
jest.mock("../../../sdk/app/permissions", () => ({
|
||||
...jest.requireActual("../../../sdk/app/permissions"),
|
||||
resourceActionAllowed: jest.fn(),
|
||||
}))
|
||||
|
||||
import sdk from "../../../sdk"
|
||||
|
||||
import { roles } from "@budibase/backend-core"
|
||||
import {
|
||||
Document,
|
||||
DocumentType,
|
||||
PermissionLevel,
|
||||
Row,
|
||||
Table,
|
||||
ViewV2,
|
||||
} from "@budibase/types"
|
||||
import { Document, PermissionLevel, Row, Table, ViewV2 } from "@budibase/types"
|
||||
import * as setup from "./utilities"
|
||||
import { generator, mocks } from "@budibase/backend-core/tests"
|
||||
|
||||
|
@ -40,7 +25,6 @@ describe("/permission", () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
mocks.licenses.useCloudFree()
|
||||
mockedSdk.resourceActionAllowed.mockResolvedValue({ allowed: true })
|
||||
|
||||
table = (await config.createTable()) as typeof table
|
||||
row = await config.createRow()
|
||||
|
@ -112,29 +96,6 @@ describe("/permission", () => {
|
|||
expect(allRes.body[table._id]["read"]).toEqual(STD_ROLE_ID)
|
||||
expect(allRes.body[table._id]["write"]).toEqual(HIGHER_ROLE_ID)
|
||||
})
|
||||
|
||||
it("throw forbidden if the action is not allowed for the resource", async () => {
|
||||
mockedSdk.resourceActionAllowed.mockResolvedValue({
|
||||
allowed: false,
|
||||
resourceType: DocumentType.DATASOURCE,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
|
||||
await config.api.permission.add(
|
||||
{
|
||||
roleId: STD_ROLE_ID,
|
||||
resourceId: table._id,
|
||||
level: PermissionLevel.EXECUTE,
|
||||
},
|
||||
{
|
||||
status: 403,
|
||||
body: {
|
||||
message:
|
||||
"You are not allowed to 'read' the resource type 'datasource'",
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("remove", () => {
|
||||
|
@ -148,29 +109,6 @@ describe("/permission", () => {
|
|||
const permsRes = await config.api.permission.get(table._id)
|
||||
expect(permsRes.permissions[STD_ROLE_ID]).toBeUndefined()
|
||||
})
|
||||
|
||||
it("throw forbidden if the action is not allowed for the resource", async () => {
|
||||
mockedSdk.resourceActionAllowed.mockResolvedValue({
|
||||
allowed: false,
|
||||
resourceType: DocumentType.DATASOURCE,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
|
||||
await config.api.permission.revoke(
|
||||
{
|
||||
roleId: STD_ROLE_ID,
|
||||
resourceId: table._id,
|
||||
level: PermissionLevel.EXECUTE,
|
||||
},
|
||||
{
|
||||
status: 403,
|
||||
body: {
|
||||
message:
|
||||
"You are not allowed to 'read' the resource type 'datasource'",
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("check public user allowed", () => {
|
||||
|
@ -206,27 +144,7 @@ describe("/permission", () => {
|
|||
await config.api.viewV2.publicSearch(view.id, undefined, { status: 401 })
|
||||
})
|
||||
|
||||
it("should ignore the view permissions if the flag is not on", async () => {
|
||||
await config.api.permission.add({
|
||||
roleId: STD_ROLE_ID,
|
||||
resourceId: view.id,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
await config.api.permission.revoke({
|
||||
roleId: STD_ROLE_ID,
|
||||
resourceId: table._id,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
// replicate changes before checking permissions
|
||||
await config.publish()
|
||||
|
||||
await config.api.viewV2.publicSearch(view.id, undefined, {
|
||||
status: 401,
|
||||
})
|
||||
})
|
||||
|
||||
it("should use the view permissions if the flag is on", async () => {
|
||||
mocks.licenses.useViewPermissions()
|
||||
it("should use the view permissions", async () => {
|
||||
await config.api.permission.add({
|
||||
roleId: STD_ROLE_ID,
|
||||
resourceId: view.id,
|
||||
|
|
|
@ -763,10 +763,6 @@ describe("/rowsActions", () => {
|
|||
})
|
||||
|
||||
describe("role permission checks", () => {
|
||||
beforeAll(() => {
|
||||
mocks.licenses.useViewPermissions()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
mocks.licenses.useCloudFree()
|
||||
})
|
||||
|
|
|
@ -2297,7 +2297,6 @@ describe.each([
|
|||
|
||||
describe("permissions", () => {
|
||||
beforeEach(async () => {
|
||||
mocks.licenses.useViewPermissions()
|
||||
await Promise.all(
|
||||
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {}))
|
||||
)
|
||||
|
|
|
@ -200,7 +200,7 @@ export function webhookValidator() {
|
|||
|
||||
export function roleValidator() {
|
||||
const permLevelArray = Object.values(permissions.PermissionLevel)
|
||||
|
||||
const permissionString = Joi.string().valid(...permLevelArray)
|
||||
return auth.joiValidator.body(
|
||||
Joi.object({
|
||||
_id: OPTIONAL_STRING,
|
||||
|
@ -208,12 +208,23 @@ export function roleValidator() {
|
|||
name: Joi.string()
|
||||
.regex(/^[a-zA-Z0-9_]*$/)
|
||||
.required(),
|
||||
uiMetadata: Joi.object({
|
||||
displayName: OPTIONAL_STRING,
|
||||
color: OPTIONAL_STRING,
|
||||
description: OPTIONAL_STRING,
|
||||
}).optional(),
|
||||
// this is the base permission ID (for now a built in)
|
||||
permissionId: Joi.string()
|
||||
.valid(...Object.values(permissions.BuiltinPermissionID))
|
||||
.required(),
|
||||
permissions: Joi.object()
|
||||
.pattern(/.*/, [Joi.string().valid(...permLevelArray)])
|
||||
.pattern(
|
||||
/.*/,
|
||||
Joi.alternatives().try(
|
||||
Joi.array().items(permissionString),
|
||||
permissionString
|
||||
)
|
||||
)
|
||||
.optional(),
|
||||
inherits: OPTIONAL_STRING,
|
||||
}).unknown(true)
|
||||
|
|
|
@ -16,6 +16,8 @@ enum Model {
|
|||
GPT_35_TURBO = "gpt-3.5-turbo",
|
||||
// will only work with api keys that have access to the GPT4 API
|
||||
GPT_4 = "gpt-4",
|
||||
GPT_4O = "gpt-4o",
|
||||
GPT_4O_MINI = "gpt-4o-mini",
|
||||
}
|
||||
|
||||
export const definition: AutomationStepDefinition = {
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
SearchFilters,
|
||||
AutomationStoppedReason,
|
||||
AutomationStatus,
|
||||
AutomationRowEvent,
|
||||
} from "@budibase/types"
|
||||
import { executeInThread } from "../threads/automation"
|
||||
import { dataFilters, sdk } from "@budibase/shared-core"
|
||||
|
@ -28,6 +29,7 @@ const JOB_OPTS = {
|
|||
removeOnFail: true,
|
||||
}
|
||||
import * as automationUtils from "../automations/automationUtils"
|
||||
import { doesTableExist } from "../sdk/app/tables/getters"
|
||||
|
||||
async function getAllAutomations() {
|
||||
const db = context.getAppDB()
|
||||
|
@ -38,25 +40,35 @@ async function getAllAutomations() {
|
|||
}
|
||||
|
||||
async function queueRelevantRowAutomations(
|
||||
event: { appId: string; row: Row; oldRow: Row },
|
||||
eventType: string
|
||||
event: AutomationRowEvent,
|
||||
eventType: AutomationEventType
|
||||
) {
|
||||
const tableId = event.row.tableId
|
||||
if (event.appId == null) {
|
||||
throw `No appId specified for ${eventType} - check event emitters.`
|
||||
}
|
||||
|
||||
// make sure table exists and is valid before proceeding
|
||||
if (!tableId || !(await doesTableExist(tableId))) {
|
||||
return
|
||||
}
|
||||
|
||||
await context.doInAppContext(event.appId, async () => {
|
||||
let automations = await getAllAutomations()
|
||||
|
||||
// filter down to the correct event type and enabled automations
|
||||
// make sure it is the correct table ID as well
|
||||
automations = automations.filter(automation => {
|
||||
const trigger = automation.definition.trigger
|
||||
return trigger && trigger.event === eventType && !automation.disabled
|
||||
return (
|
||||
trigger &&
|
||||
trigger.event === eventType &&
|
||||
!automation.disabled &&
|
||||
trigger?.inputs?.tableId === event.row.tableId
|
||||
)
|
||||
})
|
||||
|
||||
for (const automation of automations) {
|
||||
const automationDef = automation.definition
|
||||
const automationTrigger = automationDef?.trigger
|
||||
// don't queue events which are for dev apps, only way to test automations is
|
||||
// running tests on them, in production the test flag will never
|
||||
// be checked due to lazy evaluation (first always false)
|
||||
|
@ -72,11 +84,7 @@ async function queueRelevantRowAutomations(
|
|||
row: event.row,
|
||||
oldRow: event.oldRow,
|
||||
})
|
||||
if (
|
||||
automationTrigger?.inputs &&
|
||||
automationTrigger.inputs.tableId === event.row.tableId &&
|
||||
shouldTrigger
|
||||
) {
|
||||
if (shouldTrigger) {
|
||||
try {
|
||||
await automationQueue.add({ automation, event }, JOB_OPTS)
|
||||
} catch (e) {
|
||||
|
@ -87,6 +95,17 @@ async function queueRelevantRowAutomations(
|
|||
})
|
||||
}
|
||||
|
||||
async function queueRowAutomations(
|
||||
event: AutomationRowEvent,
|
||||
type: AutomationEventType
|
||||
) {
|
||||
try {
|
||||
await queueRelevantRowAutomations(event, type)
|
||||
} catch (err: any) {
|
||||
logging.logWarn("Unable to process row event", err)
|
||||
}
|
||||
}
|
||||
|
||||
emitter.on(
|
||||
AutomationEventType.ROW_SAVE,
|
||||
async function (event: UpdatedRowEventEmitter) {
|
||||
|
@ -94,7 +113,7 @@ emitter.on(
|
|||
if (!event || !event.row || !event.row.tableId) {
|
||||
return
|
||||
}
|
||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_SAVE)
|
||||
await queueRowAutomations(event, AutomationEventType.ROW_SAVE)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -103,7 +122,7 @@ emitter.on(AutomationEventType.ROW_UPDATE, async function (event) {
|
|||
if (!event || !event.row || !event.row.tableId) {
|
||||
return
|
||||
}
|
||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_UPDATE)
|
||||
await queueRowAutomations(event, AutomationEventType.ROW_UPDATE)
|
||||
})
|
||||
|
||||
emitter.on(AutomationEventType.ROW_DELETE, async function (event) {
|
||||
|
@ -111,7 +130,7 @@ emitter.on(AutomationEventType.ROW_DELETE, async function (event) {
|
|||
if (!event || !event.row || !event.row.tableId) {
|
||||
return
|
||||
}
|
||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_DELETE)
|
||||
await queueRowAutomations(event, AutomationEventType.ROW_DELETE)
|
||||
})
|
||||
|
||||
function rowPassesFilters(row: Row, filters: SearchFilters) {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { db, roles } from "@budibase/backend-core"
|
||||
import { features } from "@budibase/pro"
|
||||
import {
|
||||
DocumentType,
|
||||
PermissionLevel,
|
||||
PermissionSource,
|
||||
PlanType,
|
||||
VirtualDocumentType,
|
||||
} from "@budibase/types"
|
||||
import { extractViewInfoFromID, isViewID } from "../../../db/utils"
|
||||
|
@ -15,36 +12,6 @@ import {
|
|||
import sdk from "../../../sdk"
|
||||
import { isV2 } from "../views"
|
||||
|
||||
type ResourceActionAllowedResult =
|
||||
| { allowed: true }
|
||||
| {
|
||||
allowed: false
|
||||
level: PermissionLevel
|
||||
resourceType: DocumentType | VirtualDocumentType
|
||||
}
|
||||
|
||||
export async function resourceActionAllowed({
|
||||
resourceId,
|
||||
level,
|
||||
}: {
|
||||
resourceId: string
|
||||
level: PermissionLevel
|
||||
}): Promise<ResourceActionAllowedResult> {
|
||||
if (!isViewID(resourceId)) {
|
||||
return { allowed: true }
|
||||
}
|
||||
|
||||
if (await features.isViewPermissionEnabled()) {
|
||||
return { allowed: true }
|
||||
}
|
||||
|
||||
return {
|
||||
allowed: false,
|
||||
level,
|
||||
resourceType: VirtualDocumentType.VIEW,
|
||||
}
|
||||
}
|
||||
|
||||
type ResourcePermissions = Record<
|
||||
string,
|
||||
{ role: string; type: PermissionSource }
|
||||
|
@ -58,20 +25,6 @@ export async function getInheritablePermissions(
|
|||
}
|
||||
}
|
||||
|
||||
export async function allowsExplicitPermissions(resourceId: string) {
|
||||
if (isViewID(resourceId)) {
|
||||
const allowed = await features.isViewPermissionEnabled()
|
||||
const minPlan = !allowed ? PlanType.PREMIUM_PLUS : undefined
|
||||
|
||||
return {
|
||||
allowed,
|
||||
minPlan,
|
||||
}
|
||||
}
|
||||
|
||||
return { allowed: true }
|
||||
}
|
||||
|
||||
export async function getResourcePerms(
|
||||
resourceId: string
|
||||
): Promise<ResourcePermissions> {
|
||||
|
@ -81,16 +34,14 @@ export async function getResourcePerms(
|
|||
|
||||
const permsToInherit = await getInheritablePermissions(resourceId)
|
||||
|
||||
const allowsExplicitPerm = (await allowsExplicitPermissions(resourceId))
|
||||
.allowed
|
||||
|
||||
for (let level of CURRENTLY_SUPPORTED_LEVELS) {
|
||||
// update the various roleIds in the resource permissions
|
||||
for (let role of rolesList) {
|
||||
const rolePerms = allowsExplicitPerm
|
||||
? roles.checkForRoleResourceArray(role.permissions || {}, resourceId)
|
||||
: {}
|
||||
if (rolePerms[resourceId]?.indexOf(level) > -1) {
|
||||
const rolePerms = roles.checkForRoleResourceArray(
|
||||
role.permissions || {},
|
||||
resourceId
|
||||
)
|
||||
if (rolePerms[resourceId]?.indexOf(level as PermissionLevel) > -1) {
|
||||
permissions[level] = {
|
||||
role: roles.getExternalRoleID(role._id!, role.version),
|
||||
type: PermissionSource.EXPLICIT,
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
import { PermissionLevel } from "@budibase/types"
|
||||
import { mocks, structures } from "@budibase/backend-core/tests"
|
||||
import { resourceActionAllowed } from ".."
|
||||
import { generateViewID } from "../../../../db/utils"
|
||||
import { initProMocks } from "../../../../tests/utilities/mocks/pro"
|
||||
|
||||
initProMocks()
|
||||
|
||||
describe("permissions sdk", () => {
|
||||
beforeEach(() => {
|
||||
mocks.licenses.useCloudFree()
|
||||
})
|
||||
|
||||
describe("resourceActionAllowed", () => {
|
||||
it("non view resources actions are always allowed", async () => {
|
||||
const resourceId = structures.users.user()._id!
|
||||
|
||||
const result = await resourceActionAllowed({
|
||||
resourceId,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
|
||||
expect(result).toEqual({ allowed: true })
|
||||
})
|
||||
|
||||
it("view resources actions allowed if the feature flag is enabled", async () => {
|
||||
mocks.licenses.useViewPermissions()
|
||||
const resourceId = generateViewID(structures.generator.guid())
|
||||
|
||||
const result = await resourceActionAllowed({
|
||||
resourceId,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
|
||||
expect(result).toEqual({ allowed: true })
|
||||
})
|
||||
|
||||
it("view resources actions allowed if the feature flag is disabled", async () => {
|
||||
const resourceId = generateViewID(structures.generator.guid())
|
||||
|
||||
const result = await resourceActionAllowed({
|
||||
resourceId,
|
||||
level: PermissionLevel.READ,
|
||||
})
|
||||
|
||||
expect(result).toEqual({
|
||||
allowed: false,
|
||||
level: "read",
|
||||
resourceType: "view",
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -101,6 +101,15 @@ export async function getTable(tableId: string): Promise<Table> {
|
|||
return await processTable(output)
|
||||
}
|
||||
|
||||
export async function doesTableExist(tableId: string): Promise<boolean> {
|
||||
try {
|
||||
const table = await getTable(tableId)
|
||||
return !!table
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAllTables() {
|
||||
const [internal, external] = await Promise.all([
|
||||
getAllInternalTables(),
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
export enum RoleColor {
|
||||
ADMIN = "var(--spectrum-global-color-static-red-400)",
|
||||
POWER = "var(--spectrum-global-color-static-orange-400)",
|
||||
BASIC = "var(--spectrum-global-color-static-green-400)",
|
||||
PUBLIC = "var(--spectrum-global-color-static-blue-400)",
|
||||
BUILDER = "var(--spectrum-global-color-static-magenta-600)",
|
||||
DEFAULT_CUSTOM = "var(--spectrum-global-color-static-magenta-400)",
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
export * from "./api"
|
||||
export * from "./fields"
|
||||
export * from "./rows"
|
||||
export * from "./colors"
|
||||
|
||||
export const OperatorOptions = {
|
||||
Equals: {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { PermissionLevel, PlanType } from "../../../sdk"
|
||||
import { PermissionLevel } from "../../../sdk"
|
||||
|
||||
export interface ResourcePermissionInfo {
|
||||
role: string
|
||||
|
@ -8,7 +8,6 @@ export interface ResourcePermissionInfo {
|
|||
|
||||
export interface GetResourcePermsResponse {
|
||||
permissions: Record<string, ResourcePermissionInfo>
|
||||
requiresPlanToModify?: PlanType
|
||||
}
|
||||
|
||||
export interface GetDependantResourcesResponse {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Role } from "../../documents"
|
||||
import { Role, RoleUIMetadata } from "../../documents"
|
||||
|
||||
export interface SaveRoleRequest {
|
||||
_id?: string
|
||||
|
@ -7,6 +7,7 @@ export interface SaveRoleRequest {
|
|||
inherits: string
|
||||
permissionId: string
|
||||
version: string
|
||||
uiMetadata?: RoleUIMetadata
|
||||
}
|
||||
|
||||
export interface SaveRoleResponse extends Role {}
|
||||
|
|
|
@ -140,6 +140,8 @@ enum Model {
|
|||
GPT_35_TURBO = "gpt-3.5-turbo",
|
||||
// will only work with api keys that have access to the GPT4 API
|
||||
GPT_4 = "gpt-4",
|
||||
GPT_4O = "gpt-4o",
|
||||
GPT_4O_MINI = "gpt-4o-mini",
|
||||
}
|
||||
|
||||
export type OpenAIStepOutputs = Omit<BaseAutomationOutputs, "response"> & {
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
import { Document } from "../document"
|
||||
import { PermissionLevel } from "../../sdk"
|
||||
|
||||
export interface RoleUIMetadata {
|
||||
displayName?: string
|
||||
color?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface Role extends Document {
|
||||
permissionId: string
|
||||
inherits?: string
|
||||
permissions: { [key: string]: string[] }
|
||||
permissions: Record<string, PermissionLevel[]>
|
||||
version?: string
|
||||
name: string
|
||||
uiMetadata?: RoleUIMetadata
|
||||
}
|
||||
|
|
|
@ -74,9 +74,8 @@ export enum UserStatus {
|
|||
INACTIVE = "inactive",
|
||||
}
|
||||
|
||||
export interface UserRoles {
|
||||
[key: string]: string
|
||||
}
|
||||
// specifies a map of app ID to role ID
|
||||
export type UserRoles = Record<string, string>
|
||||
|
||||
// UTILITY TYPES
|
||||
|
||||
|
|
|
@ -15,4 +15,10 @@ export interface AutomationData {
|
|||
automation: Automation
|
||||
}
|
||||
|
||||
export interface AutomationRowEvent {
|
||||
appId: string
|
||||
row: Row
|
||||
oldRow: Row
|
||||
}
|
||||
|
||||
export type AutomationJob = Job<AutomationData>
|
||||
|
|
|
@ -13,6 +13,7 @@ export enum Feature {
|
|||
APP_BUILDERS = "appBuilders",
|
||||
OFFLINE = "offline",
|
||||
EXPANDED_PUBLIC_API = "expandedPublicApi",
|
||||
// deprecated - no longer licensed
|
||||
VIEW_PERMISSIONS = "viewPermissions",
|
||||
VIEW_READONLY_COLUMNS = "viewReadonlyColumns",
|
||||
BUDIBASE_AI = "budibaseAI",
|
||||
|
|
|
@ -35,8 +35,9 @@ describe("/api/global/roles", () => {
|
|||
|
||||
const role = new roles.Role(
|
||||
db.generateRoleID(ROLE_NAME),
|
||||
roles.BUILTIN_ROLE_IDS.BASIC,
|
||||
permissions.BuiltinPermissionID.READ_ONLY
|
||||
ROLE_NAME,
|
||||
permissions.BuiltinPermissionID.READ_ONLY,
|
||||
{ displayName: roles.BUILTIN_ROLE_IDS.BASIC }
|
||||
)
|
||||
|
||||
beforeAll(async () => {
|
||||
|
|
193
yarn.lock
193
yarn.lock
|
@ -759,20 +759,20 @@
|
|||
"@azure/abort-controller" "^1.0.0"
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/identity@^3.4.1":
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de"
|
||||
integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA==
|
||||
"@azure/identity@4.2.1", "@azure/identity@^3.4.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c"
|
||||
integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q==
|
||||
dependencies:
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
"@azure/core-auth" "^1.5.0"
|
||||
"@azure/core-client" "^1.4.0"
|
||||
"@azure/core-rest-pipeline" "^1.1.0"
|
||||
"@azure/core-tracing" "^1.0.0"
|
||||
"@azure/core-util" "^1.6.1"
|
||||
"@azure/core-util" "^1.3.0"
|
||||
"@azure/logger" "^1.0.0"
|
||||
"@azure/msal-browser" "^3.5.0"
|
||||
"@azure/msal-node" "^2.5.1"
|
||||
"@azure/msal-browser" "^3.11.1"
|
||||
"@azure/msal-node" "^2.9.2"
|
||||
events "^3.0.0"
|
||||
jws "^4.0.0"
|
||||
open "^8.0.0"
|
||||
|
@ -803,24 +803,24 @@
|
|||
dependencies:
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/msal-browser@^3.5.0":
|
||||
version "3.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.18.0.tgz#dabbde2c53195a2e0ec8404f61f337c82c159b71"
|
||||
integrity sha512-jvK5bDUWbpOaJt2Io/rjcaOVcUzkqkrCme/WntdV1SMUc67AiTcEdKuY6G/nMQ7N5Cfsk9SfpugflQwDku53yg==
|
||||
"@azure/msal-browser@^3.11.1":
|
||||
version "3.23.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.23.0.tgz#446aaf268247e5943f464f007d3aa3a04abfe95b"
|
||||
integrity sha512-+QgdMvaeEpdtgRTD7AHHq9aw8uga7mXVHV1KshO1RQ2uI5B55xJ4aEpGlg/ga3H+0arEVcRfT4ZVmX7QLXiCVw==
|
||||
dependencies:
|
||||
"@azure/msal-common" "14.13.0"
|
||||
"@azure/msal-common" "14.14.2"
|
||||
|
||||
"@azure/msal-common@14.13.0":
|
||||
version "14.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.13.0.tgz#7377b4909a46d19ea91dadd24af7705e6aa947af"
|
||||
integrity sha512-b4M/tqRzJ4jGU91BiwCsLTqChveUEyFK3qY2wGfZ0zBswIBZjAxopx5CYt5wzZFKuN15HqRDYXQbztttuIC3nA==
|
||||
"@azure/msal-common@14.14.2":
|
||||
version "14.14.2"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.14.2.tgz#583b4ac9c089953718d7a5e2f3b8df2d4dbb17f4"
|
||||
integrity sha512-XV0P5kSNwDwCA/SjIxTe9mEAsKB0NqGNSuaVrkCCE2lAyBr/D6YtD80Vkdp4tjWnPFwjzkwldjr1xU/facOJog==
|
||||
|
||||
"@azure/msal-node@^2.5.1":
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.10.0.tgz#0b893ab05dbef5c963aba080c88a0330393c4973"
|
||||
integrity sha512-JxsSE0464a8IA/+q5EHKmchwNyUFJHtCH00tSXsLaOddwLjG6yVvTH6lGgPcWMhO7YWUXj/XVgVgeE9kZtsPUQ==
|
||||
"@azure/msal-node@^2.9.2":
|
||||
version "2.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.13.1.tgz#f144371275b7c3cbe564762b84772a9732457a47"
|
||||
integrity sha512-sijfzPNorKt6+9g1/miHwhj6Iapff4mPQx1azmmZExgzUROqWTM1o3ACyxDja0g47VpowFy/sxTM/WsuCyXTiw==
|
||||
dependencies:
|
||||
"@azure/msal-common" "14.13.0"
|
||||
"@azure/msal-common" "14.14.2"
|
||||
jsonwebtoken "^9.0.0"
|
||||
uuid "^8.3.0"
|
||||
|
||||
|
@ -2053,44 +2053,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/backend-core@2.31.8":
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
"@budibase/nano" "10.1.5"
|
||||
"@budibase/pouchdb-replication-stream" "1.2.11"
|
||||
"@budibase/shared-core" "0.0.0"
|
||||
"@budibase/types" "0.0.0"
|
||||
aws-cloudfront-sign "3.0.2"
|
||||
aws-sdk "2.1030.0"
|
||||
bcrypt "5.1.0"
|
||||
bcryptjs "2.4.3"
|
||||
bull "4.10.1"
|
||||
correlation-id "4.0.0"
|
||||
dd-trace "5.2.0"
|
||||
dotenv "16.0.1"
|
||||
ioredis "5.3.2"
|
||||
joi "17.6.0"
|
||||
jsonwebtoken "9.0.2"
|
||||
knex "2.4.2"
|
||||
koa-passport "^6.0.0"
|
||||
koa-pino-logger "4.0.0"
|
||||
lodash "4.17.21"
|
||||
node-fetch "2.6.7"
|
||||
passport-google-oauth "2.0.0"
|
||||
passport-local "1.0.0"
|
||||
passport-oauth2-refresh "^2.1.0"
|
||||
pino "8.11.0"
|
||||
pino-http "8.3.3"
|
||||
posthog-node "4.0.1"
|
||||
pouchdb "7.3.0"
|
||||
pouchdb-find "7.2.2"
|
||||
redlock "4.2.0"
|
||||
rotating-file-stream "3.1.0"
|
||||
sanitize-s3-objectkey "0.0.1"
|
||||
semver "^7.5.4"
|
||||
tar-fs "2.1.1"
|
||||
uuid "^8.3.2"
|
||||
|
||||
"@budibase/handlebars-helpers@^0.13.2":
|
||||
version "0.13.2"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77"
|
||||
|
@ -2133,45 +2095,6 @@
|
|||
pouchdb-promise "^6.0.4"
|
||||
through2 "^2.0.0"
|
||||
|
||||
"@budibase/pro@npm:@budibase/pro@latest":
|
||||
version "2.31.8"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.31.8.tgz#92b27f99f815f5d20bf58bfae916760b14a036da"
|
||||
integrity sha512-nmNKVoMdUVqEIq6xqoBq0gVBCLkoPMszmn0Zu0SJ/Dc2SpsXhPz9S3n9xXfAA+FHUg9LgUAS+eKPCKPWZXtDHQ==
|
||||
dependencies:
|
||||
"@budibase/backend-core" "2.31.8"
|
||||
"@budibase/shared-core" "2.31.8"
|
||||
"@budibase/string-templates" "2.31.8"
|
||||
"@budibase/types" "2.31.8"
|
||||
"@koa/router" "8.0.8"
|
||||
bull "4.10.1"
|
||||
dd-trace "5.2.0"
|
||||
joi "17.6.0"
|
||||
jsonwebtoken "9.0.2"
|
||||
lru-cache "^7.14.1"
|
||||
memorystream "^0.3.1"
|
||||
node-fetch "2.6.7"
|
||||
scim-patch "^0.8.1"
|
||||
scim2-parse-filter "^0.2.8"
|
||||
|
||||
"@budibase/shared-core@2.31.8":
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
"@budibase/types" "0.0.0"
|
||||
cron-validate "1.4.5"
|
||||
|
||||
"@budibase/string-templates@2.31.8":
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.13.2"
|
||||
dayjs "^1.10.8"
|
||||
handlebars "^4.7.8"
|
||||
lodash.clonedeep "^4.5.0"
|
||||
|
||||
"@budibase/types@2.31.8":
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
scim-patch "^0.8.1"
|
||||
|
||||
"@bull-board/api@5.10.2":
|
||||
version "5.10.2"
|
||||
resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3"
|
||||
|
@ -6967,16 +6890,16 @@ aggregate-error@^3.0.0:
|
|||
clean-stack "^2.0.0"
|
||||
indent-string "^4.0.0"
|
||||
|
||||
airtable@0.10.1:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/airtable/-/airtable-0.10.1.tgz#0b311002bb44b39f19bf7c4bd2d47d75c733bf87"
|
||||
integrity sha512-obFW+R3ly2mKtCj0D/xto0ggUvYwdM0RJT3VJ9wvgqoxDkzqg2mNtkuTNfYjF6wWQA0GvoHG9guqzgBBqFjItw==
|
||||
airtable@0.12.2:
|
||||
version "0.12.2"
|
||||
resolved "https://registry.yarnpkg.com/airtable/-/airtable-0.12.2.tgz#e53e66db86744f9bc684faa58881d6c9c12f0e6f"
|
||||
integrity sha512-HS3VytUBTKj8A0vPl7DDr5p/w3IOGv6RXL0fv7eczOWAtj9Xe8ri4TAiZRXoOyo+Z/COADCj+oARFenbxhmkIg==
|
||||
dependencies:
|
||||
"@types/node" ">=8.0.0 <15"
|
||||
abort-controller "^3.0.0"
|
||||
abortcontroller-polyfill "^1.4.0"
|
||||
lodash "^4.17.19"
|
||||
node-fetch "^2.6.1"
|
||||
lodash "^4.17.21"
|
||||
node-fetch "^2.6.7"
|
||||
|
||||
ajv-formats@^2.0.2:
|
||||
version "2.1.1"
|
||||
|
@ -11367,27 +11290,13 @@ fast-url-parser@^1.1.3:
|
|||
dependencies:
|
||||
punycode "^1.3.2"
|
||||
|
||||
fast-xml-parser@4.2.5:
|
||||
version "4.2.5"
|
||||
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f"
|
||||
integrity "sha1-pnR6CSlqbLNPKuY0AZvxc487Qh8= sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g=="
|
||||
dependencies:
|
||||
strnum "^1.0.5"
|
||||
|
||||
fast-xml-parser@^4.1.3:
|
||||
fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.1.3, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f"
|
||||
integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==
|
||||
dependencies:
|
||||
strnum "^1.0.5"
|
||||
|
||||
fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz#341cc98de71e9ba9e651a67f41f1752d1441a501"
|
||||
integrity sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==
|
||||
dependencies:
|
||||
strnum "^1.0.5"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
|
||||
|
@ -13253,7 +13162,7 @@ is-boolean-object@^1.1.0:
|
|||
call-bind "^1.0.2"
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-buffer@^1.1.5, is-buffer@~1.1.6:
|
||||
is-buffer@~1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
@ -14653,14 +14562,7 @@ kill-port@^1.6.1:
|
|||
get-them-args "1.3.2"
|
||||
shell-exec "1.0.2"
|
||||
|
||||
kind-of@^3.0.2, kind-of@^3.1.0:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||
integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==
|
||||
dependencies:
|
||||
is-buffer "^1.1.5"
|
||||
|
||||
kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
|
||||
kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
|
||||
|
@ -15485,7 +15387,7 @@ lodash.xor@^4.5.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6"
|
||||
integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ==
|
||||
|
||||
lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0:
|
||||
lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
@ -17798,11 +17700,21 @@ periscopic@^3.1.0:
|
|||
estree-walker "^3.0.0"
|
||||
is-reference "^3.0.0"
|
||||
|
||||
pg-cloudflare@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
|
||||
integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==
|
||||
|
||||
pg-connection-string@2.5.0, pg-connection-string@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
|
||||
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
|
||||
|
||||
pg-connection-string@^2.6.4:
|
||||
version "2.6.4"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d"
|
||||
integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==
|
||||
|
||||
pg-int8@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
|
||||
|
@ -17813,11 +17725,21 @@ pg-pool@^3.6.0:
|
|||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.0.tgz#3190df3e4747a0d23e5e9e8045bcd99bda0a712e"
|
||||
integrity sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==
|
||||
|
||||
pg-pool@^3.6.2:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2"
|
||||
integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==
|
||||
|
||||
pg-protocol@*, pg-protocol@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833"
|
||||
integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==
|
||||
|
||||
pg-protocol@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3"
|
||||
integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==
|
||||
|
||||
pg-types@^2.1.0, pg-types@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
|
||||
|
@ -17842,6 +17764,19 @@ pg@8.10.0:
|
|||
pg-types "^2.1.0"
|
||||
pgpass "1.x"
|
||||
|
||||
pg@^8.12.0:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.12.0.tgz#9341724db571022490b657908f65aee8db91df79"
|
||||
integrity sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==
|
||||
dependencies:
|
||||
pg-connection-string "^2.6.4"
|
||||
pg-pool "^3.6.2"
|
||||
pg-protocol "^1.6.1"
|
||||
pg-types "^2.1.0"
|
||||
pgpass "1.x"
|
||||
optionalDependencies:
|
||||
pg-cloudflare "^1.1.1"
|
||||
|
||||
pgpass@1.x:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"
|
||||
|
|
Loading…
Reference in New Issue