Merge branch 'master' into default-app-design
This commit is contained in:
commit
99403c29e3
|
@ -56,7 +56,10 @@
|
||||||
memo,
|
memo,
|
||||||
fetchData,
|
fetchData,
|
||||||
} from "@budibase/frontend-core"
|
} from "@budibase/frontend-core"
|
||||||
import { getSchemaForDatasourcePlus } from "@/dataBinding"
|
import {
|
||||||
|
getSchemaForDatasourcePlus,
|
||||||
|
readableToRuntimeBinding,
|
||||||
|
} from "@/dataBinding"
|
||||||
import { TriggerStepID, ActionStepID } from "@/constants/backend/automations"
|
import { TriggerStepID, ActionStepID } from "@/constants/backend/automations"
|
||||||
import { onMount, createEventDispatcher } from "svelte"
|
import { onMount, createEventDispatcher } from "svelte"
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
|
@ -1034,7 +1037,10 @@
|
||||||
{bindings}
|
{bindings}
|
||||||
{schema}
|
{schema}
|
||||||
panel={AutomationBindingPanel}
|
panel={AutomationBindingPanel}
|
||||||
on:change={e => onChange({ [key]: e.detail })}
|
on:change={e =>
|
||||||
|
onChange({
|
||||||
|
[key]: readableToRuntimeBinding(bindings, e.detail),
|
||||||
|
})}
|
||||||
context={$memoContext}
|
context={$memoContext}
|
||||||
value={inputData[key]}
|
value={inputData[key]}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -37,7 +37,7 @@ const { ContextScopes } = Constants
|
||||||
|
|
||||||
// Regex to match all instances of template strings
|
// Regex to match all instances of template strings
|
||||||
const CAPTURE_VAR_INSIDE_TEMPLATE = /{{([^}]+)}}/g
|
const CAPTURE_VAR_INSIDE_TEMPLATE = /{{([^}]+)}}/g
|
||||||
const CAPTURE_VAR_INSIDE_JS = /\$\("([^")]+)"\)/g
|
const CAPTURE_VAR_INSIDE_JS = /\$\((["'`])([^"'`]+)\1\)/g
|
||||||
const CAPTURE_HBS_TEMPLATE = /{{[\S\s]*?}}/g
|
const CAPTURE_HBS_TEMPLATE = /{{[\S\s]*?}}/g
|
||||||
|
|
||||||
const UpdateReferenceAction = {
|
const UpdateReferenceAction = {
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import {
|
||||||
|
CreateOAuth2ConfigRequest,
|
||||||
|
Ctx,
|
||||||
|
FetchOAuth2ConfigsResponse,
|
||||||
|
OAuth2Config,
|
||||||
|
RequiredKeys,
|
||||||
|
} from "@budibase/types"
|
||||||
|
import sdk from "../../sdk"
|
||||||
|
|
||||||
|
export async function fetch(ctx: Ctx<void, FetchOAuth2ConfigsResponse>) {
|
||||||
|
const configs = await sdk.oauth2.fetch()
|
||||||
|
|
||||||
|
const response: FetchOAuth2ConfigsResponse = {
|
||||||
|
configs: (configs || []).map(c => ({
|
||||||
|
name: c.name,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
ctx.body = response
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function create(ctx: Ctx<CreateOAuth2ConfigRequest, void>) {
|
||||||
|
const newConfig: RequiredKeys<OAuth2Config> = {
|
||||||
|
name: ctx.request.body.name,
|
||||||
|
}
|
||||||
|
|
||||||
|
await sdk.oauth2.create(newConfig)
|
||||||
|
ctx.status = 201
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import debugRoutes from "./debug"
|
||||||
import Router from "@koa/router"
|
import Router from "@koa/router"
|
||||||
import { api as pro } from "@budibase/pro"
|
import { api as pro } from "@budibase/pro"
|
||||||
import rowActionRoutes from "./rowAction"
|
import rowActionRoutes from "./rowAction"
|
||||||
|
import oauth2Routes from "./oauth2"
|
||||||
|
|
||||||
export { default as staticRoutes } from "./static"
|
export { default as staticRoutes } from "./static"
|
||||||
export { default as publicRoutes } from "./public"
|
export { default as publicRoutes } from "./public"
|
||||||
|
@ -69,6 +70,7 @@ export const mainRoutes: Router[] = [
|
||||||
environmentVariableRoutes,
|
environmentVariableRoutes,
|
||||||
rowActionRoutes,
|
rowActionRoutes,
|
||||||
proAiRoutes,
|
proAiRoutes,
|
||||||
|
oauth2Routes,
|
||||||
// these need to be handled last as they still use /api/:tableId
|
// these need to be handled last as they still use /api/:tableId
|
||||||
// this could be breaking as koa may recognise other routes as this
|
// this could be breaking as koa may recognise other routes as this
|
||||||
tableRoutes,
|
tableRoutes,
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import Router from "@koa/router"
|
||||||
|
import { PermissionType } from "@budibase/types"
|
||||||
|
import authorized from "../../middleware/authorized"
|
||||||
|
|
||||||
|
import * as controller from "../controllers/oauth2"
|
||||||
|
|
||||||
|
const router: Router = new Router()
|
||||||
|
|
||||||
|
router.get("/api/oauth2", authorized(PermissionType.BUILDER), controller.fetch)
|
||||||
|
router.post(
|
||||||
|
"/api/oauth2",
|
||||||
|
authorized(PermissionType.BUILDER),
|
||||||
|
controller.create
|
||||||
|
)
|
||||||
|
|
||||||
|
export default router
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { CreateOAuth2ConfigRequest } from "@budibase/types"
|
||||||
|
import * as setup from "./utilities"
|
||||||
|
import { generator } from "@budibase/backend-core/tests"
|
||||||
|
|
||||||
|
describe("/oauth2", () => {
|
||||||
|
let config = setup.getConfig()
|
||||||
|
|
||||||
|
function makeOAuth2Config(): CreateOAuth2ConfigRequest {
|
||||||
|
return {
|
||||||
|
name: generator.guid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(async () => await config.init())
|
||||||
|
|
||||||
|
beforeEach(async () => await config.newTenant())
|
||||||
|
|
||||||
|
describe("fetch", () => {
|
||||||
|
it("returns empty when no oauth are created", async () => {
|
||||||
|
const response = await config.api.oauth2.fetch()
|
||||||
|
expect(response).toEqual({
|
||||||
|
configs: [],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("create", () => {
|
||||||
|
it("can create a new configuration", async () => {
|
||||||
|
const oauth2Config = makeOAuth2Config()
|
||||||
|
await config.api.oauth2.create(oauth2Config, { status: 201 })
|
||||||
|
|
||||||
|
const response = await config.api.oauth2.fetch()
|
||||||
|
expect(response).toEqual({
|
||||||
|
configs: [
|
||||||
|
{
|
||||||
|
name: oauth2Config.name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("can create multiple configurations", async () => {
|
||||||
|
const oauth2Config = makeOAuth2Config()
|
||||||
|
const oauth2Config2 = makeOAuth2Config()
|
||||||
|
await config.api.oauth2.create(oauth2Config, { status: 201 })
|
||||||
|
await config.api.oauth2.create(oauth2Config2, { status: 201 })
|
||||||
|
|
||||||
|
const response = await config.api.oauth2.fetch()
|
||||||
|
expect(response.configs).toEqual([
|
||||||
|
{
|
||||||
|
name: oauth2Config.name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: oauth2Config2.name,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("cannot create configurations with already existing names", async () => {
|
||||||
|
const oauth2Config = makeOAuth2Config()
|
||||||
|
const oauth2Config2 = { ...makeOAuth2Config(), name: oauth2Config.name }
|
||||||
|
await config.api.oauth2.create(oauth2Config, { status: 201 })
|
||||||
|
await config.api.oauth2.create(oauth2Config2, {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: "Name already used",
|
||||||
|
status: 400,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const response = await config.api.oauth2.fetch()
|
||||||
|
expect(response.configs).toEqual([
|
||||||
|
{
|
||||||
|
name: oauth2Config.name,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { context, HTTPError } from "@budibase/backend-core"
|
||||||
|
import { DocumentType, OAuth2Config, OAuth2Configs } from "@budibase/types"
|
||||||
|
|
||||||
|
export async function fetch(): Promise<OAuth2Config[]> {
|
||||||
|
const db = context.getAppDB()
|
||||||
|
const result = await db.tryGet<OAuth2Configs>(DocumentType.OAUTH2_CONFIG)
|
||||||
|
if (!result) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return Object.values(result.configs)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function create(config: OAuth2Config) {
|
||||||
|
const db = context.getAppDB()
|
||||||
|
const doc: OAuth2Configs = (await db.tryGet<OAuth2Configs>(
|
||||||
|
DocumentType.OAUTH2_CONFIG
|
||||||
|
)) ?? {
|
||||||
|
_id: DocumentType.OAUTH2_CONFIG,
|
||||||
|
configs: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.configs[config.name]) {
|
||||||
|
throw new HTTPError("Name already used", 400)
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.configs[config.name] = config
|
||||||
|
await db.put(doc)
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import * as permissions from "./app/permissions"
|
||||||
import * as rowActions from "./app/rowActions"
|
import * as rowActions from "./app/rowActions"
|
||||||
import * as screens from "./app/screens"
|
import * as screens from "./app/screens"
|
||||||
import * as common from "./app/common"
|
import * as common from "./app/common"
|
||||||
|
import * as oauth2 from "./app/oauth2"
|
||||||
|
|
||||||
const sdk = {
|
const sdk = {
|
||||||
backups,
|
backups,
|
||||||
|
@ -30,6 +31,7 @@ const sdk = {
|
||||||
links,
|
links,
|
||||||
rowActions,
|
rowActions,
|
||||||
common,
|
common,
|
||||||
|
oauth2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// default export for TS
|
// default export for TS
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { WebhookAPI } from "./webhook"
|
||||||
import { EnvironmentAPI } from "./environment"
|
import { EnvironmentAPI } from "./environment"
|
||||||
import { UserPublicAPI } from "./public/user"
|
import { UserPublicAPI } from "./public/user"
|
||||||
import { MiscAPI } from "./misc"
|
import { MiscAPI } from "./misc"
|
||||||
|
import { OAuth2API } from "./oauth2"
|
||||||
|
|
||||||
export default class API {
|
export default class API {
|
||||||
application: ApplicationAPI
|
application: ApplicationAPI
|
||||||
|
@ -30,6 +31,7 @@ export default class API {
|
||||||
environment: EnvironmentAPI
|
environment: EnvironmentAPI
|
||||||
legacyView: LegacyViewAPI
|
legacyView: LegacyViewAPI
|
||||||
misc: MiscAPI
|
misc: MiscAPI
|
||||||
|
oauth2: OAuth2API
|
||||||
permission: PermissionAPI
|
permission: PermissionAPI
|
||||||
plugin: PluginAPI
|
plugin: PluginAPI
|
||||||
query: QueryAPI
|
query: QueryAPI
|
||||||
|
@ -56,6 +58,7 @@ export default class API {
|
||||||
this.environment = new EnvironmentAPI(config)
|
this.environment = new EnvironmentAPI(config)
|
||||||
this.legacyView = new LegacyViewAPI(config)
|
this.legacyView = new LegacyViewAPI(config)
|
||||||
this.misc = new MiscAPI(config)
|
this.misc = new MiscAPI(config)
|
||||||
|
this.oauth2 = new OAuth2API(config)
|
||||||
this.permission = new PermissionAPI(config)
|
this.permission = new PermissionAPI(config)
|
||||||
this.plugin = new PluginAPI(config)
|
this.plugin = new PluginAPI(config)
|
||||||
this.query = new QueryAPI(config)
|
this.query = new QueryAPI(config)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import {
|
||||||
|
CreateOAuth2ConfigRequest,
|
||||||
|
FetchOAuth2ConfigsResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
|
import { Expectations, TestAPI } from "./base"
|
||||||
|
|
||||||
|
export class OAuth2API extends TestAPI {
|
||||||
|
fetch = async (expectations?: Expectations) => {
|
||||||
|
return await this._get<FetchOAuth2ConfigsResponse>("/api/oauth2", {
|
||||||
|
expectations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
create = async (
|
||||||
|
body: CreateOAuth2ConfigRequest,
|
||||||
|
expectations?: Expectations
|
||||||
|
) => {
|
||||||
|
return await this._post<CreateOAuth2ConfigRequest>("/api/oauth2", {
|
||||||
|
body,
|
||||||
|
expectations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,22 @@
|
||||||
export * from "./backup"
|
|
||||||
export * from "./datasource"
|
|
||||||
export * from "./view"
|
|
||||||
export * from "./rows"
|
|
||||||
export * from "./table"
|
|
||||||
export * from "./permission"
|
|
||||||
export * from "./attachment"
|
|
||||||
export * from "./user"
|
|
||||||
export * from "./rowAction"
|
|
||||||
export * from "./automation"
|
|
||||||
export * from "./component"
|
|
||||||
export * from "./integration"
|
|
||||||
export * from "./metadata"
|
|
||||||
export * from "./query"
|
|
||||||
export * from "./screen"
|
|
||||||
export * from "./application"
|
export * from "./application"
|
||||||
export * from "./layout"
|
export * from "./attachment"
|
||||||
|
export * from "./automation"
|
||||||
|
export * from "./backup"
|
||||||
|
export * from "./component"
|
||||||
|
export * from "./datasource"
|
||||||
export * from "./deployment"
|
export * from "./deployment"
|
||||||
|
export * from "./integration"
|
||||||
|
export * from "./layout"
|
||||||
|
export * from "./metadata"
|
||||||
|
export * from "./oauth2"
|
||||||
|
export * from "./permission"
|
||||||
|
export * from "./query"
|
||||||
export * from "./role"
|
export * from "./role"
|
||||||
export * from "./webhook"
|
export * from "./rowAction"
|
||||||
|
export * from "./rows"
|
||||||
|
export * from "./screen"
|
||||||
export * from "./static"
|
export * from "./static"
|
||||||
|
export * from "./table"
|
||||||
|
export * from "./user"
|
||||||
|
export * from "./view"
|
||||||
|
export * from "./webhook"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
interface OAuth2Config {
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchOAuth2ConfigsResponse {
|
||||||
|
configs: OAuth2Config[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateOAuth2ConfigRequest extends OAuth2Config {}
|
|
@ -1,22 +1,23 @@
|
||||||
|
export * from "../document"
|
||||||
export * from "./app"
|
export * from "./app"
|
||||||
export * from "./automation"
|
export * from "./automation"
|
||||||
|
export * from "./backup"
|
||||||
|
export * from "./component"
|
||||||
export * from "./datasource"
|
export * from "./datasource"
|
||||||
|
export * from "./deployment"
|
||||||
export * from "./layout"
|
export * from "./layout"
|
||||||
|
export * from "./links"
|
||||||
|
export * from "./metadata"
|
||||||
|
export * from "./oauth2"
|
||||||
export * from "./query"
|
export * from "./query"
|
||||||
export * from "./role"
|
export * from "./role"
|
||||||
export * from "./table"
|
|
||||||
export * from "./screen"
|
|
||||||
export * from "./view"
|
|
||||||
export * from "../document"
|
|
||||||
export * from "./row"
|
export * from "./row"
|
||||||
export * from "./user"
|
|
||||||
export * from "./backup"
|
|
||||||
export * from "./webhook"
|
|
||||||
export * from "./links"
|
|
||||||
export * from "./component"
|
|
||||||
export * from "./sqlite"
|
|
||||||
export * from "./snippet"
|
|
||||||
export * from "./rowAction"
|
export * from "./rowAction"
|
||||||
|
export * from "./screen"
|
||||||
|
export * from "./snippet"
|
||||||
|
export * from "./sqlite"
|
||||||
|
export * from "./table"
|
||||||
export * from "./theme"
|
export * from "./theme"
|
||||||
export * from "./deployment"
|
export * from "./user"
|
||||||
export * from "./metadata"
|
export * from "./view"
|
||||||
|
export * from "./webhook"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Document } from "../document"
|
||||||
|
|
||||||
|
export interface OAuth2Config {
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OAuth2Configs extends Document {
|
||||||
|
configs: Record<string, OAuth2Config>
|
||||||
|
}
|
|
@ -40,6 +40,7 @@ export enum DocumentType {
|
||||||
APP_MIGRATION_METADATA = "_design/migrations",
|
APP_MIGRATION_METADATA = "_design/migrations",
|
||||||
SCIM_LOG = "scimlog",
|
SCIM_LOG = "scimlog",
|
||||||
ROW_ACTIONS = "ra",
|
ROW_ACTIONS = "ra",
|
||||||
|
OAUTH2_CONFIG = "oauth2",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because DocumentTypes can overlap, we need to make sure that we search
|
// Because DocumentTypes can overlap, we need to make sure that we search
|
||||||
|
|
Loading…
Reference in New Issue