@budibase/server 2.4.42-alpha.8 → 2.4.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/assets/favicon.e7fc7733.png +0 -0
- package/builder/assets/{index.89bb7cf4.js → index.8b377b88.js} +384 -385
- package/builder/assets/index.b0e3aca6.css +6 -0
- package/builder/index.html +7 -7
- package/dist/api/controllers/application.js +24 -28
- package/dist/api/controllers/row/external.js +0 -15
- package/dist/api/controllers/static/index.js +24 -84
- package/dist/api/controllers/static/templates/BudibaseApp.svelte +11 -34
- package/dist/api/controllers/table/utils.js +4 -2
- package/dist/api/routes/public/index.js +0 -8
- package/dist/app.js +0 -1
- package/dist/integrations/googlesheets.js +0 -4
- package/dist/integrations/redis.js +1 -1
- package/dist/middleware/currentapp.js +27 -1
- package/dist/package.json +12 -13
- package/dist/sdk/users/utils.js +6 -11
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/filesystem.js +0 -4
- package/dist/utilities/global.js +7 -17
- package/jest.config.ts +1 -1
- package/package.json +13 -14
- package/scripts/test.sh +5 -3
- package/specs/openapi.json +0 -39
- package/specs/openapi.yaml +0 -169
- package/specs/resources/application.ts +0 -11
- package/specs/resources/index.ts +0 -2
- package/src/api/controllers/application.ts +21 -20
- package/src/api/controllers/row/external.ts +0 -14
- package/src/api/controllers/static/index.ts +26 -69
- package/src/api/controllers/static/templates/BudibaseApp.svelte +11 -34
- package/src/api/controllers/table/utils.ts +12 -20
- package/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap +48 -48
- package/src/api/routes/public/index.ts +1 -10
- package/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap +22 -22
- package/src/api/routes/tests/__snapshots__/view.spec.js.snap +5 -5
- package/src/api/routes/tests/appSync.spec.ts +1 -1
- package/src/api/routes/tests/internalSearch.spec.js +6 -6
- package/src/app.ts +1 -2
- package/src/automations/automationUtils.ts +1 -1
- package/src/automations/tests/automation.spec.js +84 -0
- package/src/db/defaultData/datasource_bb_default.ts +1 -1
- package/src/definitions/openapi.ts +0 -15
- package/src/integrations/googlesheets.ts +0 -4
- package/src/integrations/redis.ts +1 -1
- package/src/integrations/tests/googlesheets.spec.ts +0 -4
- package/src/integrations/tests/redis.spec.ts +5 -9
- package/src/middleware/currentapp.ts +32 -3
- package/src/middleware/tests/currentapp.spec.js +42 -6
- package/src/sdk/users/utils.ts +7 -18
- package/src/tests/jestSetup.ts +1 -5
- package/src/tests/utilities/TestConfiguration.ts +19 -7
- package/src/tests/utilities/structures.ts +1 -13
- package/src/utilities/fileSystem/filesystem.ts +0 -4
- package/src/utilities/global.ts +9 -21
- package/src/utilities/rowProcessor/index.ts +1 -1
- package/builder/assets/index.7f9a008b.css +0 -6
- package/dist/api/controllers/public/metrics.js +0 -113
- package/dist/api/routes/public/metrics.js +0 -30
- package/specs/resources/metrics.ts +0 -81
- package/src/api/controllers/public/metrics.ts +0 -251
- package/src/api/controllers/table/tests/utils.spec.ts +0 -97
- package/src/api/routes/public/metrics.ts +0 -28
- package/src/api/routes/public/tests/metrics.spec.js +0 -34
- package/src/automations/tests/automation.spec.ts +0 -99
- package/src/sdk/users/tests/utils.spec.ts +0 -159
|
@@ -23,7 +23,7 @@ import { LoopStep, LoopStepType, LoopInput } from "../definitions/automations"
|
|
|
23
23
|
* @returns {object} The inputs object which has had all the various types supported by this function converted to their
|
|
24
24
|
* primitive types.
|
|
25
25
|
*/
|
|
26
|
-
export function cleanInputValues(inputs: Record<string, any>, schema
|
|
26
|
+
export function cleanInputValues(inputs: Record<string, any>, schema: any) {
|
|
27
27
|
if (schema == null) {
|
|
28
28
|
return inputs
|
|
29
29
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
jest.mock("../../threads/automation")
|
|
2
|
+
jest.mock("../../utilities/redis", () => ({
|
|
3
|
+
init: jest.fn(),
|
|
4
|
+
checkTestFlag: () => {
|
|
5
|
+
return false
|
|
6
|
+
},
|
|
7
|
+
}))
|
|
8
|
+
|
|
9
|
+
jest.spyOn(global.console, "error")
|
|
10
|
+
|
|
11
|
+
require("../../environment")
|
|
12
|
+
const automation = require("../index")
|
|
13
|
+
const thread = require("../../threads/automation")
|
|
14
|
+
const triggers = require("../triggers")
|
|
15
|
+
const { basicAutomation } = require("../../tests/utilities/structures")
|
|
16
|
+
const { wait } = require("../../utilities")
|
|
17
|
+
const { makePartial } = require("../../tests/utilities")
|
|
18
|
+
const { cleanInputValues } = require("../automationUtils")
|
|
19
|
+
const setup = require("./utilities")
|
|
20
|
+
|
|
21
|
+
describe("Run through some parts of the automations system", () => {
|
|
22
|
+
let config = setup.getConfig()
|
|
23
|
+
|
|
24
|
+
beforeAll(async () => {
|
|
25
|
+
await automation.init()
|
|
26
|
+
await config.init()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
afterAll(setup.afterAll)
|
|
30
|
+
|
|
31
|
+
it("should be able to init in builder", async () => {
|
|
32
|
+
await triggers.externalTrigger(basicAutomation(), { a: 1, appId: config.appId })
|
|
33
|
+
await wait(100)
|
|
34
|
+
expect(thread.execute).toHaveBeenCalled()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it("should check coercion", async () => {
|
|
38
|
+
const table = await config.createTable()
|
|
39
|
+
const automation = basicAutomation()
|
|
40
|
+
automation.definition.trigger.inputs.tableId = table._id
|
|
41
|
+
automation.definition.trigger.stepId = "APP"
|
|
42
|
+
automation.definition.trigger.inputs.fields = { a: "number" }
|
|
43
|
+
await triggers.externalTrigger(automation, {
|
|
44
|
+
appId: config.getAppId(),
|
|
45
|
+
fields: {
|
|
46
|
+
a: "1"
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
await wait(100)
|
|
50
|
+
expect(thread.execute).toHaveBeenCalledWith(makePartial({
|
|
51
|
+
data: {
|
|
52
|
+
event: {
|
|
53
|
+
fields: {
|
|
54
|
+
a: 1
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}), expect.any(Function))
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it("should be able to clean inputs with the utilities", () => {
|
|
62
|
+
// can't clean without a schema
|
|
63
|
+
let output = cleanInputValues({a: "1"})
|
|
64
|
+
expect(output.a).toBe("1")
|
|
65
|
+
output = cleanInputValues({a: "1", b: "true", c: "false", d: 1, e: "help"}, {
|
|
66
|
+
properties: {
|
|
67
|
+
a: {
|
|
68
|
+
type: "number",
|
|
69
|
+
},
|
|
70
|
+
b: {
|
|
71
|
+
type: "boolean",
|
|
72
|
+
},
|
|
73
|
+
c: {
|
|
74
|
+
type: "boolean",
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
expect(output.a).toBe(1)
|
|
79
|
+
expect(output.b).toBe(true)
|
|
80
|
+
expect(output.c).toBe(false)
|
|
81
|
+
expect(output.d).toBe(1)
|
|
82
|
+
expect(output.e).toBe("help")
|
|
83
|
+
})
|
|
84
|
+
})
|
|
@@ -34,7 +34,7 @@ function syncLastIds(table: Table, rowCount: number) {
|
|
|
34
34
|
})
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function tableImport(table: Table, data: Row
|
|
37
|
+
function tableImport(table: Table, data: Row) {
|
|
38
38
|
const cloneTable = cloneDeep(table)
|
|
39
39
|
const rowDocs = importToRows(data, cloneTable)
|
|
40
40
|
syncLastIds(cloneTable, rowDocs.length)
|
|
@@ -22,10 +22,6 @@ export interface paths {
|
|
|
22
22
|
/** Based on application properties (currently only name) search for applications. */
|
|
23
23
|
post: operations["appSearch"];
|
|
24
24
|
};
|
|
25
|
-
"/metrics": {
|
|
26
|
-
/** Output metrics in OpenMetrics format compatible with Prometheus */
|
|
27
|
-
get: operations["metricsGet"];
|
|
28
|
-
};
|
|
29
25
|
"/queries/{queryId}": {
|
|
30
26
|
/** Queries which have been created within a Budibase app can be executed using this, */
|
|
31
27
|
post: operations["queryExecute"];
|
|
@@ -848,17 +844,6 @@ export interface operations {
|
|
|
848
844
|
};
|
|
849
845
|
};
|
|
850
846
|
};
|
|
851
|
-
/** Output metrics in OpenMetrics format compatible with Prometheus */
|
|
852
|
-
metricsGet: {
|
|
853
|
-
responses: {
|
|
854
|
-
/** Returns tenant metrics. */
|
|
855
|
-
200: {
|
|
856
|
-
content: {
|
|
857
|
-
"text/plain": string;
|
|
858
|
-
};
|
|
859
|
-
};
|
|
860
|
-
};
|
|
861
|
-
};
|
|
862
847
|
/** Queries which have been created within a Budibase app can be executed using this, */
|
|
863
848
|
queryExecute: {
|
|
864
849
|
parameters: {
|
|
@@ -245,10 +245,6 @@ class GoogleSheetsIntegration implements DatasourcePlus {
|
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
|
248
|
-
// not fully configured yet
|
|
249
|
-
if (!this.config.auth) {
|
|
250
|
-
return
|
|
251
|
-
}
|
|
252
248
|
await this.connect()
|
|
253
249
|
const sheets = this.client.sheetsByIndex
|
|
254
250
|
const tables: Record<string, Table> = {}
|
|
@@ -39,10 +39,6 @@ describe("Google Sheets Integration", () => {
|
|
|
39
39
|
config.setGoogleAuth("test")
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
afterAll(async () => {
|
|
43
|
-
await config.end()
|
|
44
|
-
})
|
|
45
|
-
|
|
46
42
|
beforeEach(async () => {
|
|
47
43
|
integration = new GoogleSheetsIntegration.integration({
|
|
48
44
|
spreadsheetId: "randomId",
|
|
@@ -3,17 +3,17 @@ import { default as RedisIntegration } from "../redis"
|
|
|
3
3
|
|
|
4
4
|
class TestConfiguration {
|
|
5
5
|
integration: any
|
|
6
|
+
redis: any
|
|
6
7
|
|
|
7
8
|
constructor(config: any = {}) {
|
|
8
9
|
this.integration = new RedisIntegration.integration(config)
|
|
9
|
-
|
|
10
|
-
this.integration.client.quit()
|
|
11
|
-
this.integration.client = new Redis({
|
|
10
|
+
this.redis = new Redis({
|
|
12
11
|
data: {
|
|
13
12
|
test: "test",
|
|
14
13
|
result: "1",
|
|
15
14
|
},
|
|
16
15
|
})
|
|
16
|
+
this.integration.client = this.redis
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -24,17 +24,13 @@ describe("Redis Integration", () => {
|
|
|
24
24
|
config = new TestConfiguration()
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
-
afterAll(() => {
|
|
28
|
-
config.integration.disconnect()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
27
|
it("calls the create method with the correct params", async () => {
|
|
32
28
|
const body = {
|
|
33
29
|
key: "key",
|
|
34
30
|
value: "value",
|
|
35
31
|
}
|
|
36
32
|
await config.integration.create(body)
|
|
37
|
-
expect(await config.
|
|
33
|
+
expect(await config.redis.get("key")).toEqual("value")
|
|
38
34
|
})
|
|
39
35
|
|
|
40
36
|
it("calls the read method with the correct params", async () => {
|
|
@@ -50,7 +46,7 @@ describe("Redis Integration", () => {
|
|
|
50
46
|
key: "test",
|
|
51
47
|
}
|
|
52
48
|
await config.integration.delete(body)
|
|
53
|
-
expect(await config.
|
|
49
|
+
expect(await config.redis.get(body.key)).toEqual(null)
|
|
54
50
|
})
|
|
55
51
|
|
|
56
52
|
it("calls the pipeline method with the correct params", async () => {
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
utils,
|
|
3
3
|
constants,
|
|
4
4
|
roles,
|
|
5
|
+
db as dbCore,
|
|
5
6
|
tenancy,
|
|
6
7
|
context,
|
|
7
8
|
} from "@budibase/backend-core"
|
|
@@ -9,15 +10,34 @@ import { generateUserMetadataID, isDevAppID } from "../db/utils"
|
|
|
9
10
|
import { getCachedSelf } from "../utilities/global"
|
|
10
11
|
import env from "../environment"
|
|
11
12
|
import { isWebhookEndpoint } from "./utils"
|
|
12
|
-
import {
|
|
13
|
+
import { BBContext } from "@budibase/types"
|
|
13
14
|
|
|
14
|
-
export default async (ctx:
|
|
15
|
+
export default async (ctx: BBContext, next: any) => {
|
|
15
16
|
// try to get the appID from the request
|
|
16
17
|
let requestAppId = await utils.getAppIdFromCtx(ctx)
|
|
17
|
-
if
|
|
18
|
+
// get app cookie if it exists
|
|
19
|
+
let appCookie: { appId?: string } | undefined
|
|
20
|
+
try {
|
|
21
|
+
appCookie = utils.getCookie(ctx, constants.Cookie.CurrentApp)
|
|
22
|
+
} catch (err) {
|
|
23
|
+
utils.clearCookie(ctx, constants.Cookie.CurrentApp)
|
|
24
|
+
}
|
|
25
|
+
if (!appCookie && !requestAppId) {
|
|
18
26
|
return next()
|
|
19
27
|
}
|
|
20
28
|
|
|
29
|
+
// check the app exists referenced in cookie
|
|
30
|
+
if (appCookie) {
|
|
31
|
+
const appId = appCookie.appId
|
|
32
|
+
const exists = await dbCore.dbExists(appId)
|
|
33
|
+
if (!exists) {
|
|
34
|
+
utils.clearCookie(ctx, constants.Cookie.CurrentApp)
|
|
35
|
+
return next()
|
|
36
|
+
}
|
|
37
|
+
// if the request app ID wasn't set, update it with the cookie
|
|
38
|
+
requestAppId = requestAppId || appId
|
|
39
|
+
}
|
|
40
|
+
|
|
21
41
|
// deny access to application preview
|
|
22
42
|
if (!env.isTest()) {
|
|
23
43
|
if (
|
|
@@ -25,6 +45,7 @@ export default async (ctx: UserCtx, next: any) => {
|
|
|
25
45
|
!isWebhookEndpoint(ctx) &&
|
|
26
46
|
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
|
|
27
47
|
) {
|
|
48
|
+
utils.clearCookie(ctx, constants.Cookie.CurrentApp)
|
|
28
49
|
return ctx.redirect("/")
|
|
29
50
|
}
|
|
30
51
|
}
|
|
@@ -106,6 +127,14 @@ export default async (ctx: UserCtx, next: any) => {
|
|
|
106
127
|
role: await roles.getRole(roleId),
|
|
107
128
|
}
|
|
108
129
|
}
|
|
130
|
+
if (
|
|
131
|
+
(requestAppId !== appId ||
|
|
132
|
+
appCookie == null ||
|
|
133
|
+
appCookie.appId !== requestAppId) &&
|
|
134
|
+
!skipCookie
|
|
135
|
+
) {
|
|
136
|
+
utils.setCookie(ctx, { appId }, constants.Cookie.CurrentApp)
|
|
137
|
+
}
|
|
109
138
|
|
|
110
139
|
return next()
|
|
111
140
|
})
|
|
@@ -158,22 +158,27 @@ describe("Current app middleware", () => {
|
|
|
158
158
|
})
|
|
159
159
|
|
|
160
160
|
describe("check functionality when logged in", () => {
|
|
161
|
-
async function checkExpected() {
|
|
161
|
+
async function checkExpected(setCookie) {
|
|
162
162
|
config.setUser()
|
|
163
163
|
await config.executeMiddleware()
|
|
164
|
-
|
|
164
|
+
let { utils } = require("@budibase/backend-core")
|
|
165
|
+
if (setCookie) {
|
|
166
|
+
expect(utils.setCookie).toHaveBeenCalled()
|
|
167
|
+
} else {
|
|
168
|
+
expect(utils.setCookie).not.toHaveBeenCalled()
|
|
169
|
+
}
|
|
165
170
|
expect(config.ctx.roleId).toEqual("PUBLIC")
|
|
166
171
|
expect(config.ctx.user.role._id).toEqual("PUBLIC")
|
|
167
172
|
expect(config.ctx.appId).toEqual("app_test")
|
|
168
173
|
expect(config.next).toHaveBeenCalled()
|
|
169
174
|
}
|
|
170
175
|
|
|
171
|
-
it("should be able to setup an app token
|
|
176
|
+
it("should be able to setup an app token when cookie not setup", async () => {
|
|
172
177
|
mockAuthWithCookie()
|
|
173
|
-
await checkExpected()
|
|
178
|
+
await checkExpected(true)
|
|
174
179
|
})
|
|
175
180
|
|
|
176
|
-
it("should perform correct
|
|
181
|
+
it("should perform correct when no cookie exists", async () => {
|
|
177
182
|
mockReset()
|
|
178
183
|
jest.mock("@budibase/backend-core", () => {
|
|
179
184
|
const core = jest.requireActual("@budibase/backend-core")
|
|
@@ -201,7 +206,38 @@ describe("Current app middleware", () => {
|
|
|
201
206
|
},
|
|
202
207
|
}
|
|
203
208
|
})
|
|
204
|
-
await checkExpected()
|
|
209
|
+
await checkExpected(true)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it("lastly check what occurs when cookie doesn't need updated", async () => {
|
|
213
|
+
mockReset()
|
|
214
|
+
jest.mock("@budibase/backend-core", () => {
|
|
215
|
+
const core = jest.requireActual("@budibase/backend-core")
|
|
216
|
+
return {
|
|
217
|
+
...core,
|
|
218
|
+
db: {
|
|
219
|
+
...core.db,
|
|
220
|
+
dbExists: () => true,
|
|
221
|
+
},
|
|
222
|
+
utils: {
|
|
223
|
+
getAppIdFromCtx: () => {
|
|
224
|
+
return "app_test"
|
|
225
|
+
},
|
|
226
|
+
setCookie: jest.fn(),
|
|
227
|
+
getCookie: () => ({ appId: "app_test", roleId: "PUBLIC" }),
|
|
228
|
+
},
|
|
229
|
+
cache: {
|
|
230
|
+
user: {
|
|
231
|
+
getUser: async id => {
|
|
232
|
+
return {
|
|
233
|
+
_id: "us_uuid1",
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
await checkExpected(false)
|
|
205
241
|
})
|
|
206
242
|
})
|
|
207
243
|
})
|
package/src/sdk/users/utils.ts
CHANGED
|
@@ -6,33 +6,22 @@ import {
|
|
|
6
6
|
InternalTables,
|
|
7
7
|
} from "../../db/utils"
|
|
8
8
|
import { isEqual } from "lodash"
|
|
9
|
-
import { ContextUser, UserMetadata } from "@budibase/types"
|
|
10
9
|
|
|
11
|
-
export function combineMetadataAndUser(
|
|
12
|
-
user: ContextUser,
|
|
13
|
-
metadata: UserMetadata | UserMetadata[]
|
|
14
|
-
) {
|
|
15
|
-
const metadataId = generateUserMetadataID(user._id!)
|
|
16
|
-
const found = Array.isArray(metadata)
|
|
17
|
-
? metadata.find(doc => doc._id === metadataId)
|
|
18
|
-
: metadata
|
|
10
|
+
export function combineMetadataAndUser(user: any, metadata: any) {
|
|
19
11
|
// skip users with no access
|
|
20
|
-
if (
|
|
21
|
-
user.roleId == null ||
|
|
22
|
-
user.roleId === rolesCore.BUILTIN_ROLE_IDS.PUBLIC
|
|
23
|
-
) {
|
|
24
|
-
// If it exists and it should not, we must remove it
|
|
25
|
-
if (found?._id) {
|
|
26
|
-
return { ...found, _deleted: true }
|
|
27
|
-
}
|
|
12
|
+
if (user.roleId === rolesCore.BUILTIN_ROLE_IDS.PUBLIC) {
|
|
28
13
|
return null
|
|
29
14
|
}
|
|
30
15
|
delete user._rev
|
|
16
|
+
const metadataId = generateUserMetadataID(user._id)
|
|
31
17
|
const newDoc = {
|
|
32
18
|
...user,
|
|
33
19
|
_id: metadataId,
|
|
34
20
|
tableId: InternalTables.USER_METADATA,
|
|
35
21
|
}
|
|
22
|
+
const found = Array.isArray(metadata)
|
|
23
|
+
? metadata.find(doc => doc._id === metadataId)
|
|
24
|
+
: metadata
|
|
36
25
|
// copy rev over for the purposes of equality check
|
|
37
26
|
if (found) {
|
|
38
27
|
newDoc._rev = found._rev
|
|
@@ -66,7 +55,7 @@ export async function syncGlobalUsers() {
|
|
|
66
55
|
])
|
|
67
56
|
const toWrite = []
|
|
68
57
|
for (let user of users) {
|
|
69
|
-
const combined = combineMetadataAndUser(user, metadata)
|
|
58
|
+
const combined = await combineMetadataAndUser(user, metadata)
|
|
70
59
|
if (combined) {
|
|
71
60
|
toWrite.push(combined)
|
|
72
61
|
}
|
package/src/tests/jestSetup.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./logging"
|
|
2
2
|
import env from "../environment"
|
|
3
|
-
import { env as coreEnv
|
|
3
|
+
import { env as coreEnv } from "@budibase/backend-core"
|
|
4
4
|
import { testContainerUtils } from "@budibase/backend-core/tests"
|
|
5
5
|
|
|
6
6
|
if (!process.env.DEBUG) {
|
|
@@ -17,7 +17,3 @@ if (!process.env.CI) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
testContainerUtils.setupEnv(env, coreEnv)
|
|
20
|
-
|
|
21
|
-
afterAll(() => {
|
|
22
|
-
timers.cleanup()
|
|
23
|
-
})
|
|
@@ -47,7 +47,6 @@ import {
|
|
|
47
47
|
SourceName,
|
|
48
48
|
Table,
|
|
49
49
|
SearchFilters,
|
|
50
|
-
UserRoles,
|
|
51
50
|
} from "@budibase/types"
|
|
52
51
|
|
|
53
52
|
type DefaultUserValues = {
|
|
@@ -166,8 +165,6 @@ class TestConfiguration {
|
|
|
166
165
|
}
|
|
167
166
|
if (this.server) {
|
|
168
167
|
this.server.close()
|
|
169
|
-
} else {
|
|
170
|
-
require("../../app").default.close()
|
|
171
168
|
}
|
|
172
169
|
if (this.allApps) {
|
|
173
170
|
cleanup(this.allApps.map(app => app.appId))
|
|
@@ -278,7 +275,7 @@ class TestConfiguration {
|
|
|
278
275
|
email?: string
|
|
279
276
|
builder?: boolean
|
|
280
277
|
admin?: boolean
|
|
281
|
-
roles?:
|
|
278
|
+
roles?: any
|
|
282
279
|
} = {}
|
|
283
280
|
) {
|
|
284
281
|
let { id, firstName, lastName, email, builder, admin, roles } = user
|
|
@@ -331,13 +328,21 @@ class TestConfiguration {
|
|
|
331
328
|
sessionId: "sessionid",
|
|
332
329
|
tenantId: this.getTenantId(),
|
|
333
330
|
}
|
|
331
|
+
const app = {
|
|
332
|
+
roleId: roleId,
|
|
333
|
+
appId,
|
|
334
|
+
}
|
|
334
335
|
const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET)
|
|
336
|
+
const appToken = auth.jwt.sign(app, coreEnv.JWT_SECRET)
|
|
335
337
|
|
|
336
338
|
// returning necessary request headers
|
|
337
339
|
await cache.user.invalidateUser(userId)
|
|
338
340
|
return {
|
|
339
341
|
Accept: "application/json",
|
|
340
|
-
Cookie: [
|
|
342
|
+
Cookie: [
|
|
343
|
+
`${constants.Cookie.Auth}=${authToken}`,
|
|
344
|
+
`${constants.Cookie.CurrentApp}=${appToken}`,
|
|
345
|
+
],
|
|
341
346
|
[constants.Header.APP_ID]: appId,
|
|
342
347
|
}
|
|
343
348
|
})
|
|
@@ -352,11 +357,18 @@ class TestConfiguration {
|
|
|
352
357
|
sessionId: "sessionid",
|
|
353
358
|
tenantId,
|
|
354
359
|
}
|
|
360
|
+
const app = {
|
|
361
|
+
roleId: roles.BUILTIN_ROLE_IDS.ADMIN,
|
|
362
|
+
appId: this.appId,
|
|
363
|
+
}
|
|
355
364
|
const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET)
|
|
356
|
-
|
|
365
|
+
const appToken = auth.jwt.sign(app, coreEnv.JWT_SECRET)
|
|
357
366
|
const headers: any = {
|
|
358
367
|
Accept: "application/json",
|
|
359
|
-
Cookie: [
|
|
368
|
+
Cookie: [
|
|
369
|
+
`${constants.Cookie.Auth}=${authToken}`,
|
|
370
|
+
`${constants.Cookie.CurrentApp}=${appToken}`,
|
|
371
|
+
],
|
|
360
372
|
[constants.Header.CSRF_TOKEN]: this.defaultUserValues.csrfToken,
|
|
361
373
|
Host: this.tenantHost(),
|
|
362
374
|
...extras,
|
|
@@ -106,7 +106,7 @@ export function newAutomation({ steps, trigger }: any = {}) {
|
|
|
106
106
|
return automation
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
export function basicAutomation(
|
|
109
|
+
export function basicAutomation() {
|
|
110
110
|
return {
|
|
111
111
|
name: "My Automation",
|
|
112
112
|
screenId: "kasdkfldsafkl",
|
|
@@ -114,23 +114,11 @@ export function basicAutomation(appId?: string) {
|
|
|
114
114
|
uiTree: {},
|
|
115
115
|
definition: {
|
|
116
116
|
trigger: {
|
|
117
|
-
stepId: AutomationTriggerStepId.APP,
|
|
118
|
-
name: "test",
|
|
119
|
-
tagline: "test",
|
|
120
|
-
icon: "test",
|
|
121
|
-
description: "test",
|
|
122
|
-
type: "trigger",
|
|
123
|
-
id: "test",
|
|
124
117
|
inputs: {},
|
|
125
|
-
schema: {
|
|
126
|
-
inputs: {},
|
|
127
|
-
outputs: {},
|
|
128
|
-
},
|
|
129
118
|
},
|
|
130
119
|
steps: [],
|
|
131
120
|
},
|
|
132
121
|
type: "automation",
|
|
133
|
-
appId,
|
|
134
122
|
}
|
|
135
123
|
}
|
|
136
124
|
|
|
@@ -24,10 +24,6 @@ export const init = () => {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
const clientLibPath = join(budibaseTempDir(), "budibase-client.js")
|
|
28
|
-
if (env.isTest() && !fs.existsSync(clientLibPath)) {
|
|
29
|
-
fs.copyFileSync(require.resolve("@budibase/client"), clientLibPath)
|
|
30
|
-
}
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
/**
|
package/src/utilities/global.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "@budibase/backend-core"
|
|
9
9
|
import env from "../environment"
|
|
10
10
|
import { groups } from "@budibase/pro"
|
|
11
|
-
import {
|
|
11
|
+
import { BBContext, ContextUser, User } from "@budibase/types"
|
|
12
12
|
|
|
13
13
|
export function updateAppRole(
|
|
14
14
|
user: ContextUser,
|
|
@@ -43,40 +43,33 @@ export function updateAppRole(
|
|
|
43
43
|
|
|
44
44
|
async function checkGroupRoles(
|
|
45
45
|
user: ContextUser,
|
|
46
|
-
|
|
46
|
+
{ appId }: { appId?: string } = {}
|
|
47
47
|
) {
|
|
48
48
|
if (user.roleId && user.roleId !== roles.BUILTIN_ROLE_IDS.PUBLIC) {
|
|
49
49
|
return user
|
|
50
50
|
}
|
|
51
|
-
if (
|
|
52
|
-
user.roleId = await groups.getGroupRoleId(user as User,
|
|
53
|
-
groups: opts.groups,
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
// final fallback, simply couldn't find a role - user must be public
|
|
57
|
-
if (!user.roleId) {
|
|
58
|
-
user.roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
|
|
51
|
+
if (appId) {
|
|
52
|
+
user.roleId = await groups.getGroupRoleId(user as User, appId)
|
|
59
53
|
}
|
|
60
54
|
return user
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
async function processUser(
|
|
64
58
|
user: ContextUser,
|
|
65
|
-
|
|
59
|
+
{ appId }: { appId?: string } = {}
|
|
66
60
|
) {
|
|
67
61
|
if (user) {
|
|
68
62
|
delete user.password
|
|
69
63
|
}
|
|
70
|
-
|
|
71
|
-
user = updateAppRole(user, { appId })
|
|
64
|
+
user = await updateAppRole(user, { appId })
|
|
72
65
|
if (!user.roleId && user?.userGroups?.length) {
|
|
73
|
-
user = await checkGroupRoles(user, { appId
|
|
66
|
+
user = await checkGroupRoles(user, { appId })
|
|
74
67
|
}
|
|
75
68
|
|
|
76
69
|
return user
|
|
77
70
|
}
|
|
78
71
|
|
|
79
|
-
export async function getCachedSelf(ctx:
|
|
72
|
+
export async function getCachedSelf(ctx: BBContext, appId: string) {
|
|
80
73
|
// this has to be tenant aware, can't depend on the context to find it out
|
|
81
74
|
// running some middlewares before the tenancy causes context to break
|
|
82
75
|
const user = await cache.user.getUser(ctx.user?._id!)
|
|
@@ -97,7 +90,6 @@ export async function getGlobalUser(userId: string) {
|
|
|
97
90
|
export async function getGlobalUsers(users?: ContextUser[]) {
|
|
98
91
|
const appId = context.getAppId()
|
|
99
92
|
const db = tenancy.getGlobalDB()
|
|
100
|
-
const allGroups = await groups.fetch()
|
|
101
93
|
let globalUsers
|
|
102
94
|
if (users) {
|
|
103
95
|
const globalIds = users.map(user =>
|
|
@@ -126,11 +118,7 @@ export async function getGlobalUsers(users?: ContextUser[]) {
|
|
|
126
118
|
return globalUsers
|
|
127
119
|
}
|
|
128
120
|
|
|
129
|
-
|
|
130
|
-
// each user individually
|
|
131
|
-
return Promise.all(
|
|
132
|
-
globalUsers.map(user => processUser(user, { groups: allGroups }))
|
|
133
|
-
)
|
|
121
|
+
return globalUsers.map(user => updateAppRole(user))
|
|
134
122
|
}
|
|
135
123
|
|
|
136
124
|
export async function getGlobalUsersFromMetadata(users: ContextUser[]) {
|
|
@@ -131,7 +131,7 @@ export function coerce(row: any, type: string) {
|
|
|
131
131
|
* @returns {object} the row which has been prepared to be written to the DB.
|
|
132
132
|
*/
|
|
133
133
|
export function inputProcessing(
|
|
134
|
-
user: ContextUser
|
|
134
|
+
user: ContextUser,
|
|
135
135
|
table: Table,
|
|
136
136
|
row: Row,
|
|
137
137
|
opts?: AutoColumnProcessingOpts
|