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
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
if ${{ env.ONLY_AFFECTED_TASKS }}; then
|
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
|
else
|
||||||
yarn test --ignore=@budibase/worker --ignore=@budibase/server --ignore @budibase/account-portal-server
|
yarn test --ignore=@budibase/worker --ignore=@budibase/server
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test-worker:
|
test-worker:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
"version": "2.32.0",
|
"version": "2.32.4",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
|
|
|
@ -117,7 +117,10 @@
|
||||||
"axios": "1.6.3",
|
"axios": "1.6.3",
|
||||||
"xml2js": "0.6.2",
|
"xml2js": "0.6.2",
|
||||||
"unset-value": "2.0.1",
|
"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": {
|
"engines": {
|
||||||
"node": ">=20.0.0 <21.0.0"
|
"node": ">=20.0.0 <21.0.0"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7899d07904d89d48954dd500da7b5dec32b781dd
|
Subproject commit 905773d70854a43c6ef2461c7a49671bff56fedc
|
|
@ -7,8 +7,9 @@ import {
|
||||||
doWithDB,
|
doWithDB,
|
||||||
} from "../db"
|
} from "../db"
|
||||||
import { getAppDB } from "../context"
|
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 cloneDeep from "lodash/fp/cloneDeep"
|
||||||
|
import { RoleColor } from "@budibase/shared-core"
|
||||||
|
|
||||||
export const BUILTIN_ROLE_IDS = {
|
export const BUILTIN_ROLE_IDS = {
|
||||||
ADMIN: "ADMIN",
|
ADMIN: "ADMIN",
|
||||||
|
@ -44,11 +45,18 @@ export class Role implements RoleDoc {
|
||||||
permissionId: string
|
permissionId: string
|
||||||
inherits?: string
|
inherits?: string
|
||||||
version?: 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._id = id
|
||||||
this.name = name
|
this.name = name
|
||||||
|
this.uiMetadata = uiMetadata
|
||||||
this.permissionId = permissionId
|
this.permissionId = permissionId
|
||||||
// version for managing the ID - removing the role_ when responding
|
// version for managing the ID - removing the role_ when responding
|
||||||
this.version = RoleIDVersion.NAME
|
this.version = RoleIDVersion.NAME
|
||||||
|
@ -63,21 +71,54 @@ export class Role implements RoleDoc {
|
||||||
const BUILTIN_ROLES = {
|
const BUILTIN_ROLES = {
|
||||||
ADMIN: new Role(
|
ADMIN: new Role(
|
||||||
BUILTIN_IDS.ADMIN,
|
BUILTIN_IDS.ADMIN,
|
||||||
"Admin",
|
BUILTIN_IDS.ADMIN,
|
||||||
BuiltinPermissionID.ADMIN
|
BuiltinPermissionID.ADMIN,
|
||||||
|
{
|
||||||
|
displayName: "App admin",
|
||||||
|
description: "Can do everything",
|
||||||
|
color: RoleColor.ADMIN,
|
||||||
|
}
|
||||||
).addInheritance(BUILTIN_IDS.POWER),
|
).addInheritance(BUILTIN_IDS.POWER),
|
||||||
POWER: new Role(
|
POWER: new Role(
|
||||||
BUILTIN_IDS.POWER,
|
BUILTIN_IDS.POWER,
|
||||||
"Power",
|
BUILTIN_IDS.POWER,
|
||||||
BuiltinPermissionID.POWER
|
BuiltinPermissionID.POWER,
|
||||||
|
{
|
||||||
|
displayName: "App power user",
|
||||||
|
description: "An app user with more access",
|
||||||
|
color: RoleColor.POWER,
|
||||||
|
}
|
||||||
).addInheritance(BUILTIN_IDS.BASIC),
|
).addInheritance(BUILTIN_IDS.BASIC),
|
||||||
BASIC: new Role(
|
BASIC: new Role(
|
||||||
BUILTIN_IDS.BASIC,
|
BUILTIN_IDS.BASIC,
|
||||||
"Basic",
|
BUILTIN_IDS.BASIC,
|
||||||
BuiltinPermissionID.WRITE
|
BuiltinPermissionID.WRITE,
|
||||||
|
{
|
||||||
|
displayName: "App user",
|
||||||
|
description: "Any logged in user",
|
||||||
|
color: RoleColor.BASIC,
|
||||||
|
}
|
||||||
).addInheritance(BUILTIN_IDS.PUBLIC),
|
).addInheritance(BUILTIN_IDS.PUBLIC),
|
||||||
PUBLIC: new Role(BUILTIN_IDS.PUBLIC, "Public", BuiltinPermissionID.PUBLIC),
|
PUBLIC: new Role(
|
||||||
BUILDER: new Role(BUILTIN_IDS.BUILDER, "Builder", BuiltinPermissionID.ADMIN),
|
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 } {
|
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
|
// 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
|
// convert the string to an array using the theory that write is higher than read
|
||||||
export function checkForRoleResourceArray(
|
export function checkForRoleResourceArray(
|
||||||
rolePerms: { [key: string]: string[] },
|
rolePerms: Record<string, PermissionLevel[]>,
|
||||||
resourceId: string
|
resourceId: string
|
||||||
) {
|
): Record<string, PermissionLevel[]> {
|
||||||
if (rolePerms && !Array.isArray(rolePerms[resourceId])) {
|
if (rolePerms && !Array.isArray(rolePerms[resourceId])) {
|
||||||
const permLevel = rolePerms[resourceId] as any
|
const permLevel = rolePerms[resourceId] as any
|
||||||
rolePerms[resourceId] = [permLevel]
|
rolePerms[resourceId] = [permLevel]
|
||||||
|
|
|
@ -102,10 +102,6 @@ export const useAppBuilders = () => {
|
||||||
return useFeature(Feature.APP_BUILDERS)
|
return useFeature(Feature.APP_BUILDERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useViewPermissions = () => {
|
|
||||||
return useFeature(Feature.VIEW_PERMISSIONS)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useViewReadonlyColumns = () => {
|
export const useViewReadonlyColumns = () => {
|
||||||
return useFeature(Feature.VIEW_READONLY_COLUMNS)
|
return useFeature(Feature.VIEW_READONLY_COLUMNS)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const RemoveID = "remove"
|
const RemoveID = "remove"
|
||||||
|
const subType = $licensing.license.plan.type ?? null
|
||||||
|
|
||||||
$: enrichLabel = label => (labelPrefix ? `${labelPrefix} ${label}` : label)
|
$: enrichLabel = label => (labelPrefix ? `${labelPrefix} ${label}` : label)
|
||||||
$: options = getOptions(
|
$: options = getOptions(
|
||||||
|
@ -68,13 +69,13 @@
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Add creator if required
|
// Add creator if required
|
||||||
if (allowCreator) {
|
if (allowCreator || isEnterprisePlan(subType)) {
|
||||||
options.unshift({
|
options.unshift({
|
||||||
_id: Constants.Roles.CREATOR,
|
_id: Constants.Roles.CREATOR,
|
||||||
name: "Can edit",
|
name: "Can edit",
|
||||||
tag:
|
tag: isEnterprisePlan(subType)
|
||||||
!$licensing.perAppBuildersEnabled &&
|
? null
|
||||||
capitalise(Constants.PlanType.BUSINESS),
|
: capitalise(Constants.PlanType.ENTERPRISE),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +118,14 @@
|
||||||
dispatch("change", e.detail)
|
dispatch("change", e.detail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isEnterprisePlan(subType) {
|
||||||
|
return (
|
||||||
|
subType === Constants.PlanType.ENTERPRISE ||
|
||||||
|
subType === Constants.PlanType.ENTERPRISE_BASIC ||
|
||||||
|
subType === Constants.PlanType.ENTERPRISE_BASIC_TRIAL
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if fancySelect}
|
{#if fancySelect}
|
||||||
|
@ -134,9 +143,12 @@
|
||||||
getOptionValue={role => role._id}
|
getOptionValue={role => role._id}
|
||||||
getOptionColour={getColor}
|
getOptionColour={getColor}
|
||||||
getOptionIcon={getIcon}
|
getOptionIcon={getIcon}
|
||||||
isOptionEnabled={option =>
|
isOptionEnabled={option => {
|
||||||
option._id !== Constants.Roles.CREATOR ||
|
if (option._id === Constants.Roles.CREATOR) {
|
||||||
$licensing.perAppBuildersEnabled}
|
return isEnterprisePlan(subType)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
{error}
|
{error}
|
||||||
/>
|
/>
|
||||||
|
@ -154,10 +166,12 @@
|
||||||
getOptionValue={role => role._id}
|
getOptionValue={role => role._id}
|
||||||
getOptionColour={getColor}
|
getOptionColour={getColor}
|
||||||
getOptionIcon={getIcon}
|
getOptionIcon={getIcon}
|
||||||
isOptionEnabled={option =>
|
isOptionEnabled={option => {
|
||||||
(option._id !== Constants.Roles.CREATOR ||
|
if (option._id === Constants.Roles.CREATOR) {
|
||||||
$licensing.perAppBuildersEnabled) &&
|
return isEnterprisePlan(subType)
|
||||||
option.enabled !== false}
|
}
|
||||||
|
return option.enabled !== false
|
||||||
|
}}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
{error}
|
{error}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -85,6 +85,7 @@ export const PlanType = {
|
||||||
TEAM: "team",
|
TEAM: "team",
|
||||||
PRO: "pro",
|
PRO: "pro",
|
||||||
BUSINESS: "business",
|
BUSINESS: "business",
|
||||||
|
PREMIUM: "premium",
|
||||||
ENTERPRISE: "enterprise",
|
ENTERPRISE: "enterprise",
|
||||||
ENTERPRISE_BASIC_TRIAL: "enterprise_basic_trial",
|
ENTERPRISE_BASIC_TRIAL: "enterprise_basic_trial",
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ec1d2bda756f02c6b4efdee086e4c59b0c2a1b0c
|
Subproject commit 922431260e90d558a1ca55398475412e75088057
|
|
@ -63,7 +63,7 @@
|
||||||
"@koa/router": "8.0.8",
|
"@koa/router": "8.0.8",
|
||||||
"@socket.io/redis-adapter": "^8.2.1",
|
"@socket.io/redis-adapter": "^8.2.1",
|
||||||
"@types/xml2js": "^0.4.14",
|
"@types/xml2js": "^0.4.14",
|
||||||
"airtable": "0.10.1",
|
"airtable": "0.12.2",
|
||||||
"arangojs": "7.2.0",
|
"arangojs": "7.2.0",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"aws-sdk": "2.1030.0",
|
"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 {
|
import {
|
||||||
UserCtx,
|
UserCtx,
|
||||||
Database,
|
Database,
|
||||||
|
@ -45,18 +45,6 @@ async function updatePermissionOnRole(
|
||||||
}: { roleId: string; resourceId: string; level: PermissionLevel },
|
}: { roleId: string; resourceId: string; level: PermissionLevel },
|
||||||
updateType: PermissionUpdateType
|
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 db = context.getAppDB()
|
||||||
const remove = updateType === PermissionUpdateType.REMOVE
|
const remove = updateType === PermissionUpdateType.REMOVE
|
||||||
const isABuiltin = roles.isBuiltin(roleId)
|
const isABuiltin = roles.isBuiltin(roleId)
|
||||||
|
@ -75,7 +63,9 @@ async function updatePermissionOnRole(
|
||||||
// resource from another role and then adding to the new role
|
// resource from another role and then adding to the new role
|
||||||
for (let role of dbRoles) {
|
for (let role of dbRoles) {
|
||||||
let updated = false
|
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
|
// make sure its an array, also handle migrating
|
||||||
if (
|
if (
|
||||||
!rolePermissions[resourceId] ||
|
!rolePermissions[resourceId] ||
|
||||||
|
@ -83,7 +73,7 @@ async function updatePermissionOnRole(
|
||||||
) {
|
) {
|
||||||
rolePermissions[resourceId] =
|
rolePermissions[resourceId] =
|
||||||
typeof rolePermissions[resourceId] === "string"
|
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
|
// handle the removal/updating the role which has this permission first
|
||||||
|
@ -182,9 +172,6 @@ export async function getResourcePerms(
|
||||||
},
|
},
|
||||||
{} as Record<string, ResourcePermissionInfo>
|
{} as Record<string, ResourcePermissionInfo>
|
||||||
),
|
),
|
||||||
requiresPlanToModify: (
|
|
||||||
await sdk.permissions.allowsExplicitPermissions(resourceId)
|
|
||||||
).minPlan,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ import {
|
||||||
SaveRoleResponse,
|
SaveRoleResponse,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
UserMetadata,
|
UserMetadata,
|
||||||
UserRoles,
|
DocumentType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { sdk as sharedSdk } from "@budibase/shared-core"
|
import { RoleColor, sdk as sharedSdk } from "@budibase/shared-core"
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
|
|
||||||
const UpdateRolesOptions = {
|
const UpdateRolesOptions = {
|
||||||
|
@ -62,7 +62,8 @@ export async function find(ctx: UserCtx<void, FindRoleResponse>) {
|
||||||
|
|
||||||
export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
||||||
const db = context.getAppDB()
|
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
|
let isCreate = false
|
||||||
const isNewVersion = version === roles.RoleIDVersion.NAME
|
const isNewVersion = version === roles.RoleIDVersion.NAME
|
||||||
|
|
||||||
|
@ -80,17 +81,25 @@ export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
||||||
_id = dbCore.prefixRoleID(_id)
|
_id = dbCore.prefixRoleID(_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
let dbRole
|
let dbRole: Role | undefined
|
||||||
if (!isCreate) {
|
if (!isCreate && _id?.startsWith(DocumentType.ROLE)) {
|
||||||
dbRole = await db.get<UserRoles>(_id)
|
dbRole = await db.get<Role>(_id)
|
||||||
}
|
}
|
||||||
if (dbRole && dbRole.name !== name && isNewVersion) {
|
if (dbRole && dbRole.name !== name && isNewVersion) {
|
||||||
ctx.throw(400, "Cannot change custom role name")
|
ctx.throw(400, "Cannot change custom role name")
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = new roles.Role(_id, name, permissionId).addInheritance(inherits)
|
const role = new roles.Role(_id, name, permissionId, {
|
||||||
if (ctx.request.body._rev) {
|
displayName: uiMetadata?.displayName || name,
|
||||||
role._rev = ctx.request.body._rev
|
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)
|
const result = await db.put(role)
|
||||||
if (isCreate) {
|
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 { roles } from "@budibase/backend-core"
|
||||||
import {
|
import { Document, PermissionLevel, Row, Table, ViewV2 } from "@budibase/types"
|
||||||
Document,
|
|
||||||
DocumentType,
|
|
||||||
PermissionLevel,
|
|
||||||
Row,
|
|
||||||
Table,
|
|
||||||
ViewV2,
|
|
||||||
} from "@budibase/types"
|
|
||||||
import * as setup from "./utilities"
|
import * as setup from "./utilities"
|
||||||
import { generator, mocks } from "@budibase/backend-core/tests"
|
import { generator, mocks } from "@budibase/backend-core/tests"
|
||||||
|
|
||||||
|
@ -40,7 +25,6 @@ describe("/permission", () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mocks.licenses.useCloudFree()
|
mocks.licenses.useCloudFree()
|
||||||
mockedSdk.resourceActionAllowed.mockResolvedValue({ allowed: true })
|
|
||||||
|
|
||||||
table = (await config.createTable()) as typeof table
|
table = (await config.createTable()) as typeof table
|
||||||
row = await config.createRow()
|
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]["read"]).toEqual(STD_ROLE_ID)
|
||||||
expect(allRes.body[table._id]["write"]).toEqual(HIGHER_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", () => {
|
describe("remove", () => {
|
||||||
|
@ -148,29 +109,6 @@ describe("/permission", () => {
|
||||||
const permsRes = await config.api.permission.get(table._id)
|
const permsRes = await config.api.permission.get(table._id)
|
||||||
expect(permsRes.permissions[STD_ROLE_ID]).toBeUndefined()
|
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", () => {
|
describe("check public user allowed", () => {
|
||||||
|
@ -206,27 +144,7 @@ describe("/permission", () => {
|
||||||
await config.api.viewV2.publicSearch(view.id, undefined, { status: 401 })
|
await config.api.viewV2.publicSearch(view.id, undefined, { status: 401 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should ignore the view permissions if the flag is not on", async () => {
|
it("should use the view permissions", 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()
|
|
||||||
await config.api.permission.add({
|
await config.api.permission.add({
|
||||||
roleId: STD_ROLE_ID,
|
roleId: STD_ROLE_ID,
|
||||||
resourceId: view.id,
|
resourceId: view.id,
|
||||||
|
|
|
@ -763,10 +763,6 @@ describe("/rowsActions", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("role permission checks", () => {
|
describe("role permission checks", () => {
|
||||||
beforeAll(() => {
|
|
||||||
mocks.licenses.useViewPermissions()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
mocks.licenses.useCloudFree()
|
mocks.licenses.useCloudFree()
|
||||||
})
|
})
|
||||||
|
|
|
@ -2297,7 +2297,6 @@ describe.each([
|
||||||
|
|
||||||
describe("permissions", () => {
|
describe("permissions", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mocks.licenses.useViewPermissions()
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {}))
|
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {}))
|
||||||
)
|
)
|
||||||
|
|
|
@ -200,7 +200,7 @@ export function webhookValidator() {
|
||||||
|
|
||||||
export function roleValidator() {
|
export function roleValidator() {
|
||||||
const permLevelArray = Object.values(permissions.PermissionLevel)
|
const permLevelArray = Object.values(permissions.PermissionLevel)
|
||||||
|
const permissionString = Joi.string().valid(...permLevelArray)
|
||||||
return auth.joiValidator.body(
|
return auth.joiValidator.body(
|
||||||
Joi.object({
|
Joi.object({
|
||||||
_id: OPTIONAL_STRING,
|
_id: OPTIONAL_STRING,
|
||||||
|
@ -208,12 +208,23 @@ export function roleValidator() {
|
||||||
name: Joi.string()
|
name: Joi.string()
|
||||||
.regex(/^[a-zA-Z0-9_]*$/)
|
.regex(/^[a-zA-Z0-9_]*$/)
|
||||||
.required(),
|
.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)
|
// this is the base permission ID (for now a built in)
|
||||||
permissionId: Joi.string()
|
permissionId: Joi.string()
|
||||||
.valid(...Object.values(permissions.BuiltinPermissionID))
|
.valid(...Object.values(permissions.BuiltinPermissionID))
|
||||||
.required(),
|
.required(),
|
||||||
permissions: Joi.object()
|
permissions: Joi.object()
|
||||||
.pattern(/.*/, [Joi.string().valid(...permLevelArray)])
|
.pattern(
|
||||||
|
/.*/,
|
||||||
|
Joi.alternatives().try(
|
||||||
|
Joi.array().items(permissionString),
|
||||||
|
permissionString
|
||||||
|
)
|
||||||
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
inherits: OPTIONAL_STRING,
|
inherits: OPTIONAL_STRING,
|
||||||
}).unknown(true)
|
}).unknown(true)
|
||||||
|
|
|
@ -16,6 +16,8 @@ enum Model {
|
||||||
GPT_35_TURBO = "gpt-3.5-turbo",
|
GPT_35_TURBO = "gpt-3.5-turbo",
|
||||||
// will only work with api keys that have access to the GPT4 API
|
// will only work with api keys that have access to the GPT4 API
|
||||||
GPT_4 = "gpt-4",
|
GPT_4 = "gpt-4",
|
||||||
|
GPT_4O = "gpt-4o",
|
||||||
|
GPT_4O_MINI = "gpt-4o-mini",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const definition: AutomationStepDefinition = {
|
export const definition: AutomationStepDefinition = {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
AutomationStoppedReason,
|
AutomationStoppedReason,
|
||||||
AutomationStatus,
|
AutomationStatus,
|
||||||
|
AutomationRowEvent,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { executeInThread } from "../threads/automation"
|
import { executeInThread } from "../threads/automation"
|
||||||
import { dataFilters, sdk } from "@budibase/shared-core"
|
import { dataFilters, sdk } from "@budibase/shared-core"
|
||||||
|
@ -28,6 +29,7 @@ const JOB_OPTS = {
|
||||||
removeOnFail: true,
|
removeOnFail: true,
|
||||||
}
|
}
|
||||||
import * as automationUtils from "../automations/automationUtils"
|
import * as automationUtils from "../automations/automationUtils"
|
||||||
|
import { doesTableExist } from "../sdk/app/tables/getters"
|
||||||
|
|
||||||
async function getAllAutomations() {
|
async function getAllAutomations() {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
@ -38,25 +40,35 @@ async function getAllAutomations() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function queueRelevantRowAutomations(
|
async function queueRelevantRowAutomations(
|
||||||
event: { appId: string; row: Row; oldRow: Row },
|
event: AutomationRowEvent,
|
||||||
eventType: string
|
eventType: AutomationEventType
|
||||||
) {
|
) {
|
||||||
|
const tableId = event.row.tableId
|
||||||
if (event.appId == null) {
|
if (event.appId == null) {
|
||||||
throw `No appId specified for ${eventType} - check event emitters.`
|
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 () => {
|
await context.doInAppContext(event.appId, async () => {
|
||||||
let automations = await getAllAutomations()
|
let automations = await getAllAutomations()
|
||||||
|
|
||||||
// filter down to the correct event type and enabled automations
|
// filter down to the correct event type and enabled automations
|
||||||
|
// make sure it is the correct table ID as well
|
||||||
automations = automations.filter(automation => {
|
automations = automations.filter(automation => {
|
||||||
const trigger = automation.definition.trigger
|
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) {
|
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
|
// 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
|
// running tests on them, in production the test flag will never
|
||||||
// be checked due to lazy evaluation (first always false)
|
// be checked due to lazy evaluation (first always false)
|
||||||
|
@ -72,11 +84,7 @@ async function queueRelevantRowAutomations(
|
||||||
row: event.row,
|
row: event.row,
|
||||||
oldRow: event.oldRow,
|
oldRow: event.oldRow,
|
||||||
})
|
})
|
||||||
if (
|
if (shouldTrigger) {
|
||||||
automationTrigger?.inputs &&
|
|
||||||
automationTrigger.inputs.tableId === event.row.tableId &&
|
|
||||||
shouldTrigger
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
await automationQueue.add({ automation, event }, JOB_OPTS)
|
await automationQueue.add({ automation, event }, JOB_OPTS)
|
||||||
} catch (e) {
|
} 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(
|
emitter.on(
|
||||||
AutomationEventType.ROW_SAVE,
|
AutomationEventType.ROW_SAVE,
|
||||||
async function (event: UpdatedRowEventEmitter) {
|
async function (event: UpdatedRowEventEmitter) {
|
||||||
|
@ -94,7 +113,7 @@ emitter.on(
|
||||||
if (!event || !event.row || !event.row.tableId) {
|
if (!event || !event.row || !event.row.tableId) {
|
||||||
return
|
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) {
|
if (!event || !event.row || !event.row.tableId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_UPDATE)
|
await queueRowAutomations(event, AutomationEventType.ROW_UPDATE)
|
||||||
})
|
})
|
||||||
|
|
||||||
emitter.on(AutomationEventType.ROW_DELETE, async function (event) {
|
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) {
|
if (!event || !event.row || !event.row.tableId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_DELETE)
|
await queueRowAutomations(event, AutomationEventType.ROW_DELETE)
|
||||||
})
|
})
|
||||||
|
|
||||||
function rowPassesFilters(row: Row, filters: SearchFilters) {
|
function rowPassesFilters(row: Row, filters: SearchFilters) {
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import { db, roles } from "@budibase/backend-core"
|
import { db, roles } from "@budibase/backend-core"
|
||||||
import { features } from "@budibase/pro"
|
|
||||||
import {
|
import {
|
||||||
DocumentType,
|
|
||||||
PermissionLevel,
|
PermissionLevel,
|
||||||
PermissionSource,
|
PermissionSource,
|
||||||
PlanType,
|
|
||||||
VirtualDocumentType,
|
VirtualDocumentType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { extractViewInfoFromID, isViewID } from "../../../db/utils"
|
import { extractViewInfoFromID, isViewID } from "../../../db/utils"
|
||||||
|
@ -15,36 +12,6 @@ import {
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
import { isV2 } from "../views"
|
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<
|
type ResourcePermissions = Record<
|
||||||
string,
|
string,
|
||||||
{ role: string; type: PermissionSource }
|
{ 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(
|
export async function getResourcePerms(
|
||||||
resourceId: string
|
resourceId: string
|
||||||
): Promise<ResourcePermissions> {
|
): Promise<ResourcePermissions> {
|
||||||
|
@ -81,16 +34,14 @@ export async function getResourcePerms(
|
||||||
|
|
||||||
const permsToInherit = await getInheritablePermissions(resourceId)
|
const permsToInherit = await getInheritablePermissions(resourceId)
|
||||||
|
|
||||||
const allowsExplicitPerm = (await allowsExplicitPermissions(resourceId))
|
|
||||||
.allowed
|
|
||||||
|
|
||||||
for (let level of CURRENTLY_SUPPORTED_LEVELS) {
|
for (let level of CURRENTLY_SUPPORTED_LEVELS) {
|
||||||
// update the various roleIds in the resource permissions
|
// update the various roleIds in the resource permissions
|
||||||
for (let role of rolesList) {
|
for (let role of rolesList) {
|
||||||
const rolePerms = allowsExplicitPerm
|
const rolePerms = roles.checkForRoleResourceArray(
|
||||||
? roles.checkForRoleResourceArray(role.permissions || {}, resourceId)
|
role.permissions || {},
|
||||||
: {}
|
resourceId
|
||||||
if (rolePerms[resourceId]?.indexOf(level) > -1) {
|
)
|
||||||
|
if (rolePerms[resourceId]?.indexOf(level as PermissionLevel) > -1) {
|
||||||
permissions[level] = {
|
permissions[level] = {
|
||||||
role: roles.getExternalRoleID(role._id!, role.version),
|
role: roles.getExternalRoleID(role._id!, role.version),
|
||||||
type: PermissionSource.EXPLICIT,
|
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)
|
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() {
|
export async function getAllTables() {
|
||||||
const [internal, external] = await Promise.all([
|
const [internal, external] = await Promise.all([
|
||||||
getAllInternalTables(),
|
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 "./api"
|
||||||
export * from "./fields"
|
export * from "./fields"
|
||||||
export * from "./rows"
|
export * from "./rows"
|
||||||
|
export * from "./colors"
|
||||||
|
|
||||||
export const OperatorOptions = {
|
export const OperatorOptions = {
|
||||||
Equals: {
|
Equals: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { PermissionLevel, PlanType } from "../../../sdk"
|
import { PermissionLevel } from "../../../sdk"
|
||||||
|
|
||||||
export interface ResourcePermissionInfo {
|
export interface ResourcePermissionInfo {
|
||||||
role: string
|
role: string
|
||||||
|
@ -8,7 +8,6 @@ export interface ResourcePermissionInfo {
|
||||||
|
|
||||||
export interface GetResourcePermsResponse {
|
export interface GetResourcePermsResponse {
|
||||||
permissions: Record<string, ResourcePermissionInfo>
|
permissions: Record<string, ResourcePermissionInfo>
|
||||||
requiresPlanToModify?: PlanType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetDependantResourcesResponse {
|
export interface GetDependantResourcesResponse {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Role } from "../../documents"
|
import { Role, RoleUIMetadata } from "../../documents"
|
||||||
|
|
||||||
export interface SaveRoleRequest {
|
export interface SaveRoleRequest {
|
||||||
_id?: string
|
_id?: string
|
||||||
|
@ -7,6 +7,7 @@ export interface SaveRoleRequest {
|
||||||
inherits: string
|
inherits: string
|
||||||
permissionId: string
|
permissionId: string
|
||||||
version: string
|
version: string
|
||||||
|
uiMetadata?: RoleUIMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SaveRoleResponse extends Role {}
|
export interface SaveRoleResponse extends Role {}
|
||||||
|
|
|
@ -140,6 +140,8 @@ enum Model {
|
||||||
GPT_35_TURBO = "gpt-3.5-turbo",
|
GPT_35_TURBO = "gpt-3.5-turbo",
|
||||||
// will only work with api keys that have access to the GPT4 API
|
// will only work with api keys that have access to the GPT4 API
|
||||||
GPT_4 = "gpt-4",
|
GPT_4 = "gpt-4",
|
||||||
|
GPT_4O = "gpt-4o",
|
||||||
|
GPT_4O_MINI = "gpt-4o-mini",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OpenAIStepOutputs = Omit<BaseAutomationOutputs, "response"> & {
|
export type OpenAIStepOutputs = Omit<BaseAutomationOutputs, "response"> & {
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
import { Document } from "../document"
|
import { Document } from "../document"
|
||||||
|
import { PermissionLevel } from "../../sdk"
|
||||||
|
|
||||||
|
export interface RoleUIMetadata {
|
||||||
|
displayName?: string
|
||||||
|
color?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface Role extends Document {
|
export interface Role extends Document {
|
||||||
permissionId: string
|
permissionId: string
|
||||||
inherits?: string
|
inherits?: string
|
||||||
permissions: { [key: string]: string[] }
|
permissions: Record<string, PermissionLevel[]>
|
||||||
version?: string
|
version?: string
|
||||||
name: string
|
name: string
|
||||||
|
uiMetadata?: RoleUIMetadata
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,9 +74,8 @@ export enum UserStatus {
|
||||||
INACTIVE = "inactive",
|
INACTIVE = "inactive",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserRoles {
|
// specifies a map of app ID to role ID
|
||||||
[key: string]: string
|
export type UserRoles = Record<string, string>
|
||||||
}
|
|
||||||
|
|
||||||
// UTILITY TYPES
|
// UTILITY TYPES
|
||||||
|
|
||||||
|
|
|
@ -15,4 +15,10 @@ export interface AutomationData {
|
||||||
automation: Automation
|
automation: Automation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AutomationRowEvent {
|
||||||
|
appId: string
|
||||||
|
row: Row
|
||||||
|
oldRow: Row
|
||||||
|
}
|
||||||
|
|
||||||
export type AutomationJob = Job<AutomationData>
|
export type AutomationJob = Job<AutomationData>
|
||||||
|
|
|
@ -13,6 +13,7 @@ export enum Feature {
|
||||||
APP_BUILDERS = "appBuilders",
|
APP_BUILDERS = "appBuilders",
|
||||||
OFFLINE = "offline",
|
OFFLINE = "offline",
|
||||||
EXPANDED_PUBLIC_API = "expandedPublicApi",
|
EXPANDED_PUBLIC_API = "expandedPublicApi",
|
||||||
|
// deprecated - no longer licensed
|
||||||
VIEW_PERMISSIONS = "viewPermissions",
|
VIEW_PERMISSIONS = "viewPermissions",
|
||||||
VIEW_READONLY_COLUMNS = "viewReadonlyColumns",
|
VIEW_READONLY_COLUMNS = "viewReadonlyColumns",
|
||||||
BUDIBASE_AI = "budibaseAI",
|
BUDIBASE_AI = "budibaseAI",
|
||||||
|
|
|
@ -35,8 +35,9 @@ describe("/api/global/roles", () => {
|
||||||
|
|
||||||
const role = new roles.Role(
|
const role = new roles.Role(
|
||||||
db.generateRoleID(ROLE_NAME),
|
db.generateRoleID(ROLE_NAME),
|
||||||
roles.BUILTIN_ROLE_IDS.BASIC,
|
ROLE_NAME,
|
||||||
permissions.BuiltinPermissionID.READ_ONLY
|
permissions.BuiltinPermissionID.READ_ONLY,
|
||||||
|
{ displayName: roles.BUILTIN_ROLE_IDS.BASIC }
|
||||||
)
|
)
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|
193
yarn.lock
193
yarn.lock
|
@ -759,20 +759,20 @@
|
||||||
"@azure/abort-controller" "^1.0.0"
|
"@azure/abort-controller" "^1.0.0"
|
||||||
tslib "^2.2.0"
|
tslib "^2.2.0"
|
||||||
|
|
||||||
"@azure/identity@^3.4.1":
|
"@azure/identity@4.2.1", "@azure/identity@^3.4.1":
|
||||||
version "3.4.2"
|
version "4.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de"
|
resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c"
|
||||||
integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA==
|
integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@azure/abort-controller" "^1.0.0"
|
"@azure/abort-controller" "^1.0.0"
|
||||||
"@azure/core-auth" "^1.5.0"
|
"@azure/core-auth" "^1.5.0"
|
||||||
"@azure/core-client" "^1.4.0"
|
"@azure/core-client" "^1.4.0"
|
||||||
"@azure/core-rest-pipeline" "^1.1.0"
|
"@azure/core-rest-pipeline" "^1.1.0"
|
||||||
"@azure/core-tracing" "^1.0.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/logger" "^1.0.0"
|
||||||
"@azure/msal-browser" "^3.5.0"
|
"@azure/msal-browser" "^3.11.1"
|
||||||
"@azure/msal-node" "^2.5.1"
|
"@azure/msal-node" "^2.9.2"
|
||||||
events "^3.0.0"
|
events "^3.0.0"
|
||||||
jws "^4.0.0"
|
jws "^4.0.0"
|
||||||
open "^8.0.0"
|
open "^8.0.0"
|
||||||
|
@ -803,24 +803,24 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.2.0"
|
tslib "^2.2.0"
|
||||||
|
|
||||||
"@azure/msal-browser@^3.5.0":
|
"@azure/msal-browser@^3.11.1":
|
||||||
version "3.18.0"
|
version "3.23.0"
|
||||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.18.0.tgz#dabbde2c53195a2e0ec8404f61f337c82c159b71"
|
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.23.0.tgz#446aaf268247e5943f464f007d3aa3a04abfe95b"
|
||||||
integrity sha512-jvK5bDUWbpOaJt2Io/rjcaOVcUzkqkrCme/WntdV1SMUc67AiTcEdKuY6G/nMQ7N5Cfsk9SfpugflQwDku53yg==
|
integrity sha512-+QgdMvaeEpdtgRTD7AHHq9aw8uga7mXVHV1KshO1RQ2uI5B55xJ4aEpGlg/ga3H+0arEVcRfT4ZVmX7QLXiCVw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@azure/msal-common" "14.13.0"
|
"@azure/msal-common" "14.14.2"
|
||||||
|
|
||||||
"@azure/msal-common@14.13.0":
|
"@azure/msal-common@14.14.2":
|
||||||
version "14.13.0"
|
version "14.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.13.0.tgz#7377b4909a46d19ea91dadd24af7705e6aa947af"
|
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.14.2.tgz#583b4ac9c089953718d7a5e2f3b8df2d4dbb17f4"
|
||||||
integrity sha512-b4M/tqRzJ4jGU91BiwCsLTqChveUEyFK3qY2wGfZ0zBswIBZjAxopx5CYt5wzZFKuN15HqRDYXQbztttuIC3nA==
|
integrity sha512-XV0P5kSNwDwCA/SjIxTe9mEAsKB0NqGNSuaVrkCCE2lAyBr/D6YtD80Vkdp4tjWnPFwjzkwldjr1xU/facOJog==
|
||||||
|
|
||||||
"@azure/msal-node@^2.5.1":
|
"@azure/msal-node@^2.9.2":
|
||||||
version "2.10.0"
|
version "2.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.10.0.tgz#0b893ab05dbef5c963aba080c88a0330393c4973"
|
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.13.1.tgz#f144371275b7c3cbe564762b84772a9732457a47"
|
||||||
integrity sha512-JxsSE0464a8IA/+q5EHKmchwNyUFJHtCH00tSXsLaOddwLjG6yVvTH6lGgPcWMhO7YWUXj/XVgVgeE9kZtsPUQ==
|
integrity sha512-sijfzPNorKt6+9g1/miHwhj6Iapff4mPQx1azmmZExgzUROqWTM1o3ACyxDja0g47VpowFy/sxTM/WsuCyXTiw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@azure/msal-common" "14.13.0"
|
"@azure/msal-common" "14.14.2"
|
||||||
jsonwebtoken "^9.0.0"
|
jsonwebtoken "^9.0.0"
|
||||||
uuid "^8.3.0"
|
uuid "^8.3.0"
|
||||||
|
|
||||||
|
@ -2053,44 +2053,6 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
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":
|
"@budibase/handlebars-helpers@^0.13.2":
|
||||||
version "0.13.2"
|
version "0.13.2"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77"
|
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77"
|
||||||
|
@ -2133,45 +2095,6 @@
|
||||||
pouchdb-promise "^6.0.4"
|
pouchdb-promise "^6.0.4"
|
||||||
through2 "^2.0.0"
|
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":
|
"@bull-board/api@5.10.2":
|
||||||
version "5.10.2"
|
version "5.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3"
|
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"
|
clean-stack "^2.0.0"
|
||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
|
|
||||||
airtable@0.10.1:
|
airtable@0.12.2:
|
||||||
version "0.10.1"
|
version "0.12.2"
|
||||||
resolved "https://registry.yarnpkg.com/airtable/-/airtable-0.10.1.tgz#0b311002bb44b39f19bf7c4bd2d47d75c733bf87"
|
resolved "https://registry.yarnpkg.com/airtable/-/airtable-0.12.2.tgz#e53e66db86744f9bc684faa58881d6c9c12f0e6f"
|
||||||
integrity sha512-obFW+R3ly2mKtCj0D/xto0ggUvYwdM0RJT3VJ9wvgqoxDkzqg2mNtkuTNfYjF6wWQA0GvoHG9guqzgBBqFjItw==
|
integrity sha512-HS3VytUBTKj8A0vPl7DDr5p/w3IOGv6RXL0fv7eczOWAtj9Xe8ri4TAiZRXoOyo+Z/COADCj+oARFenbxhmkIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" ">=8.0.0 <15"
|
"@types/node" ">=8.0.0 <15"
|
||||||
abort-controller "^3.0.0"
|
abort-controller "^3.0.0"
|
||||||
abortcontroller-polyfill "^1.4.0"
|
abortcontroller-polyfill "^1.4.0"
|
||||||
lodash "^4.17.19"
|
lodash "^4.17.21"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.7"
|
||||||
|
|
||||||
ajv-formats@^2.0.2:
|
ajv-formats@^2.0.2:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
|
@ -11367,27 +11290,13 @@ fast-url-parser@^1.1.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode "^1.3.2"
|
punycode "^1.3.2"
|
||||||
|
|
||||||
fast-xml-parser@4.2.5:
|
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.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:
|
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f"
|
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f"
|
||||||
integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==
|
integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==
|
||||||
dependencies:
|
dependencies:
|
||||||
strnum "^1.0.5"
|
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:
|
fastq@^1.6.0:
|
||||||
version "1.13.0"
|
version "1.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
|
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"
|
call-bind "^1.0.2"
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-buffer@^1.1.5, is-buffer@~1.1.6:
|
is-buffer@~1.1.6:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||||
|
@ -14653,14 +14562,7 @@ kill-port@^1.6.1:
|
||||||
get-them-args "1.3.2"
|
get-them-args "1.3.2"
|
||||||
shell-exec "1.0.2"
|
shell-exec "1.0.2"
|
||||||
|
|
||||||
kind-of@^3.0.2, kind-of@^3.1.0:
|
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 "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:
|
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||||
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
|
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"
|
resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6"
|
||||||
integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ==
|
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"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
@ -17798,11 +17700,21 @@ periscopic@^3.1.0:
|
||||||
estree-walker "^3.0.0"
|
estree-walker "^3.0.0"
|
||||||
is-reference "^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:
|
pg-connection-string@2.5.0, pg-connection-string@^2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
|
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
|
||||||
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
|
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:
|
pg-int8@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
|
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"
|
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.0.tgz#3190df3e4747a0d23e5e9e8045bcd99bda0a712e"
|
||||||
integrity sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==
|
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:
|
pg-protocol@*, pg-protocol@^1.6.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833"
|
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833"
|
||||||
integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==
|
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:
|
pg-types@^2.1.0, pg-types@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
|
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"
|
pg-types "^2.1.0"
|
||||||
pgpass "1.x"
|
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:
|
pgpass@1.x:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"
|
resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"
|
||||||
|
|
Loading…
Reference in New Issue