@budibase/server 2.3.18-alpha.12 → 2.3.18-alpha.14

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "2.3.18-alpha.12",
4
+ "version": "2.3.18-alpha.14",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -43,11 +43,11 @@
43
43
  "license": "GPL-3.0",
44
44
  "dependencies": {
45
45
  "@apidevtools/swagger-parser": "10.0.3",
46
- "@budibase/backend-core": "2.3.18-alpha.12",
47
- "@budibase/client": "2.3.18-alpha.12",
48
- "@budibase/pro": "2.3.18-alpha.10",
49
- "@budibase/string-templates": "2.3.18-alpha.12",
50
- "@budibase/types": "2.3.18-alpha.12",
46
+ "@budibase/backend-core": "2.3.18-alpha.14",
47
+ "@budibase/client": "2.3.18-alpha.14",
48
+ "@budibase/pro": "2.3.18-alpha.13",
49
+ "@budibase/string-templates": "2.3.18-alpha.14",
50
+ "@budibase/types": "2.3.18-alpha.14",
51
51
  "@bull-board/api": "3.7.0",
52
52
  "@bull-board/koa": "3.9.4",
53
53
  "@elastic/elasticsearch": "7.10.0",
@@ -173,5 +173,5 @@
173
173
  "optionalDependencies": {
174
174
  "oracledb": "5.3.0"
175
175
  },
176
- "gitHead": "f77c214b0a0a5fcee6614db7f604ad278acaf246"
176
+ "gitHead": "6303105b71c3ef85e5bc8a89a7fd763cf55179e4"
177
177
  }
@@ -58,7 +58,7 @@ export async function exportApps(ctx: Ctx) {
58
58
  }
59
59
 
60
60
  async function checkHasBeenImported() {
61
- if (!env.SELF_HOSTED || env.MULTI_TENANCY) {
61
+ if (!env.SELF_HOSTED) {
62
62
  return true
63
63
  }
64
64
  const apps = await dbCore.getAllApps({ all: true })
@@ -72,7 +72,7 @@ export async function hasBeenImported(ctx: Ctx) {
72
72
  }
73
73
 
74
74
  export async function importApps(ctx: Ctx) {
75
- if (!env.SELF_HOSTED || env.MULTI_TENANCY) {
75
+ if (!env.SELF_HOSTED) {
76
76
  ctx.throw(400, "Importing only allowed in self hosted environments.")
77
77
  }
78
78
  const beenImported = await checkHasBeenImported()
@@ -1,3 +1,5 @@
1
+ import { App } from "@budibase/types"
2
+
1
3
  jest.setTimeout(30000)
2
4
 
3
5
  import { AppStatus } from "../../../db/utils"
@@ -5,6 +7,7 @@ import { AppStatus } from "../../../db/utils"
5
7
  import * as setup from "./utilities"
6
8
 
7
9
  import { wipeDb } from "./utilities/TestFunctions"
10
+ import { tenancy } from "@budibase/backend-core"
8
11
 
9
12
  describe("/cloud", () => {
10
13
  let request = setup.getRequest()!
@@ -12,18 +15,10 @@ describe("/cloud", () => {
12
15
 
13
16
  afterAll(setup.afterAll)
14
17
 
15
- beforeAll(() => {
18
+ beforeAll(async () => {
16
19
  // Importing is only allowed in self hosted environments
17
- config.modeSelf()
18
- })
19
-
20
- beforeEach(async () => {
21
20
  await config.init()
22
- })
23
-
24
- afterEach(async () => {
25
- // clear all mocks
26
- jest.clearAllMocks()
21
+ config.modeSelf()
27
22
  })
28
23
 
29
24
  describe("import", () => {
@@ -32,30 +27,28 @@ describe("/cloud", () => {
32
27
  // import will not run
33
28
  await wipeDb()
34
29
 
35
- // get a count of apps before the import
36
- const preImportApps = await request
37
- .get(`/api/applications?status=${AppStatus.ALL}`)
38
- .set(config.defaultHeaders())
39
- .expect("Content-Type", /json/)
40
- .expect(200)
41
-
42
30
  // Perform the import
43
31
  const res = await request
44
32
  .post(`/api/cloud/import`)
33
+ .set(config.publicHeaders())
45
34
  .attach("importFile", "src/api/routes/tests/data/export-test.tar.gz")
46
- .set(config.defaultHeaders())
47
35
  .expect(200)
48
36
  expect(res.body.message).toEqual("Apps successfully imported.")
49
37
 
50
38
  // get a count of apps after the import
51
39
  const postImportApps = await request
52
40
  .get(`/api/applications?status=${AppStatus.ALL}`)
53
- .set(config.defaultHeaders())
41
+ .set(config.publicHeaders())
54
42
  .expect("Content-Type", /json/)
55
43
  .expect(200)
56
44
 
45
+ const apps = postImportApps.body as App[]
57
46
  // There are two apps in the file that was imported so check for this
58
- expect(postImportApps.body.length).toEqual(2)
47
+ expect(apps.length).toEqual(2)
48
+ // The new tenant id was assigned to the imported apps
49
+ expect(tenancy.getTenantIDFromAppID(apps[0].appId)).toBe(
50
+ config.getTenantId()
51
+ )
59
52
  })
60
53
  })
61
54
  })
@@ -2,7 +2,6 @@ import * as rowController from "../../../controllers/row"
2
2
  import * as appController from "../../../controllers/application"
3
3
  import { AppStatus } from "../../../../db/utils"
4
4
  import { roles, tenancy, context } from "@budibase/backend-core"
5
- import { TENANT_ID } from "../../../../tests/utilities/structures"
6
5
  import env from "../../../../environment"
7
6
  import { db } from "@budibase/backend-core"
8
7
  import Nano from "@budibase/nano"
@@ -33,7 +32,7 @@ export const getAllTableRows = async (config: any) => {
33
32
  }
34
33
 
35
34
  export const clearAllApps = async (
36
- tenantId = TENANT_ID,
35
+ tenantId: string,
37
36
  exceptions: Array<string> = []
38
37
  ) => {
39
38
  await tenancy.doInTenant(tenantId, async () => {
@@ -11,8 +11,7 @@ import { OAuth2Client } from "google-auth-library"
11
11
  import { buildExternalTableId } from "./utils"
12
12
  import { DataSourceOperation, FieldTypes } from "../constants"
13
13
  import { GoogleSpreadsheet } from "google-spreadsheet"
14
- import env from "../environment"
15
- import { tenancy, db as dbCore, constants } from "@budibase/backend-core"
14
+ import { configs, HTTPError } from "@budibase/backend-core"
16
15
  const fetch = require("node-fetch")
17
16
 
18
17
  interface GoogleSheetsConfig {
@@ -173,16 +172,9 @@ class GoogleSheetsIntegration implements DatasourcePlus {
173
172
  async connect() {
174
173
  try {
175
174
  // Initialise oAuth client
176
- const db = tenancy.getGlobalDB()
177
- let googleConfig = await dbCore.getScopedConfig(db, {
178
- type: constants.Config.GOOGLE,
179
- })
180
-
175
+ let googleConfig = await configs.getGoogleConfig()
181
176
  if (!googleConfig) {
182
- googleConfig = {
183
- clientID: env.GOOGLE_CLIENT_ID,
184
- clientSecret: env.GOOGLE_CLIENT_SECRET,
185
- }
177
+ throw new HTTPError("Google config not found", 400)
186
178
  }
187
179
 
188
180
  const oauthClient = new OAuth2Client({
@@ -1,4 +1,9 @@
1
- import { events, db as dbUtils } from "@budibase/backend-core"
1
+ import {
2
+ events,
3
+ DocumentType,
4
+ SEPARATOR,
5
+ UNICODE_MAX,
6
+ } from "@budibase/backend-core"
2
7
  import {
3
8
  Config,
4
9
  isSMTPConfig,
@@ -9,15 +14,16 @@ import {
9
14
  } from "@budibase/types"
10
15
  import env from "./../../../../environment"
11
16
 
17
+ export const getConfigParams = () => {
18
+ return {
19
+ include_docs: true,
20
+ startkey: `${DocumentType.CONFIG}${SEPARATOR}`,
21
+ endkey: `${DocumentType.CONFIG}${SEPARATOR}${UNICODE_MAX}`,
22
+ }
23
+ }
24
+
12
25
  const getConfigs = async (globalDb: any): Promise<Config[]> => {
13
- const response = await globalDb.allDocs(
14
- dbUtils.getConfigParams(
15
- {},
16
- {
17
- include_docs: true,
18
- }
19
- )
20
- )
26
+ const response = await globalDb.allDocs(getConfigParams())
21
27
  return response.rows.map((row: any) => row.doc)
22
28
  }
23
29
 
@@ -8,9 +8,8 @@ jest.mock("@budibase/backend-core", () => {
8
8
  }
9
9
  }
10
10
  })
11
- const { tenancy, db: dbCore } = require("@budibase/backend-core")
11
+ const { context, db: dbCore } = require("@budibase/backend-core")
12
12
  const TestConfig = require("../../../tests/utilities/TestConfiguration")
13
- const { TENANT_ID } = require("../../../tests/utilities/structures")
14
13
 
15
14
  // mock email view creation
16
15
 
@@ -26,8 +25,8 @@ describe("run", () => {
26
25
  afterAll(config.end)
27
26
 
28
27
  it("runs successfully", async () => {
29
- await tenancy.doInTenant(TENANT_ID, async () => {
30
- const globalDb = tenancy.getGlobalDB()
28
+ await config.doInTenant(async () => {
29
+ const globalDb = context.getGlobalDB()
31
30
  await migration.run(globalDb)
32
31
  expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1)
33
32
  })
@@ -1,7 +1,7 @@
1
1
  // Mimic configs test configuration from worker, creation configs directly in database
2
2
 
3
3
  import * as structures from "./structures"
4
- import { db } from "@budibase/backend-core"
4
+ import { configs } from "@budibase/backend-core"
5
5
  import { Config } from "@budibase/types"
6
6
 
7
7
  export const saveSettingsConfig = async (globalDb: any) => {
@@ -25,7 +25,7 @@ export const saveSmtpConfig = async (globalDb: any) => {
25
25
  }
26
26
 
27
27
  const saveConfig = async (config: Config, globalDb: any) => {
28
- config._id = db.generateConfigID({ type: config.type })
28
+ config._id = configs.generateConfigID(config.type)
29
29
 
30
30
  let response
31
31
  try {
@@ -20,6 +20,7 @@ export const oidc = (conf?: OIDCConfig): OIDCConfig => {
20
20
  name: "Active Directory",
21
21
  uuid: utils.newid(),
22
22
  activated: true,
23
+ scopes: [],
23
24
  ...conf,
24
25
  },
25
26
  ],
@@ -8,3 +8,4 @@ process.env.BUDIBASE_DIR = tmpdir("budibase-unittests")
8
8
  process.env.LOG_LEVEL = process.env.LOG_LEVEL || "error"
9
9
  process.env.ENABLE_4XX_HTTP_LOGGING = "0"
10
10
  process.env.MOCK_REDIS = "1"
11
+ process.env.PLATFORM_URL = "http://localhost:10000"
@@ -21,7 +21,6 @@ import {
21
21
  basicScreen,
22
22
  basicLayout,
23
23
  basicWebhook,
24
- TENANT_ID,
25
24
  } from "./structures"
26
25
  import {
27
26
  constants,
@@ -41,8 +40,8 @@ import { generateUserMetadataID } from "../../db/utils"
41
40
  import { startup } from "../../startup"
42
41
  import supertest from "supertest"
43
42
  import {
43
+ App,
44
44
  AuthToken,
45
- Database,
46
45
  Datasource,
47
46
  Row,
48
47
  SourceName,
@@ -63,7 +62,7 @@ class TestConfiguration {
63
62
  started: boolean
64
63
  appId: string | null
65
64
  allApps: any[]
66
- app: any
65
+ app?: App
67
66
  prodApp: any
68
67
  prodAppId: any
69
68
  user: any
@@ -73,7 +72,7 @@ class TestConfiguration {
73
72
  linkedTable: any
74
73
  automation: any
75
74
  datasource: any
76
- tenantId: string | null
75
+ tenantId?: string
77
76
  defaultUserValues: DefaultUserValues
78
77
 
79
78
  constructor(openServer = true) {
@@ -89,7 +88,6 @@ class TestConfiguration {
89
88
  }
90
89
  this.appId = null
91
90
  this.allApps = []
92
- this.tenantId = null
93
91
  this.defaultUserValues = this.populateDefaultUserValues()
94
92
  }
95
93
 
@@ -154,19 +152,10 @@ class TestConfiguration {
154
152
 
155
153
  // use a new id as the name to avoid name collisions
156
154
  async init(appName = newid()) {
157
- this.defaultUserValues = this.populateDefaultUserValues()
158
- if (context.isMultiTenant()) {
159
- this.tenantId = structures.tenant.id()
160
- }
161
-
162
155
  if (!this.started) {
163
156
  await startup()
164
157
  }
165
- this.user = await this.globalUser()
166
- this.globalUserId = this.user._id
167
- this.userMetadataId = generateUserMetadataID(this.globalUserId)
168
-
169
- return this.createApp(appName)
158
+ return this.newTenant(appName)
170
159
  }
171
160
 
172
161
  end() {
@@ -182,24 +171,22 @@ class TestConfiguration {
182
171
  }
183
172
 
184
173
  // MODES
185
- #setMultiTenancy = (value: boolean) => {
174
+ setMultiTenancy = (value: boolean) => {
186
175
  env._set("MULTI_TENANCY", value)
187
176
  coreEnv._set("MULTI_TENANCY", value)
188
177
  }
189
178
 
190
- #setSelfHosted = (value: boolean) => {
179
+ setSelfHosted = (value: boolean) => {
191
180
  env._set("SELF_HOSTED", value)
192
181
  coreEnv._set("SELF_HOSTED", value)
193
182
  }
194
183
 
195
184
  modeCloud = () => {
196
- this.#setSelfHosted(false)
197
- this.#setMultiTenancy(true)
185
+ this.setSelfHosted(false)
198
186
  }
199
187
 
200
188
  modeSelf = () => {
201
- this.#setSelfHosted(true)
202
- this.#setMultiTenancy(false)
189
+ this.setSelfHosted(true)
203
190
  }
204
191
 
205
192
  // UTILS
@@ -354,6 +341,8 @@ class TestConfiguration {
354
341
  })
355
342
  }
356
343
 
344
+ // HEADERS
345
+
357
346
  defaultHeaders(extras = {}) {
358
347
  const tenantId = this.getTenantId()
359
348
  const authObj: AuthToken = {
@@ -374,6 +363,7 @@ class TestConfiguration {
374
363
  `${constants.Cookie.CurrentApp}=${appToken}`,
375
364
  ],
376
365
  [constants.Header.CSRF_TOKEN]: this.defaultUserValues.csrfToken,
366
+ Host: this.tenantHost(),
377
367
  ...extras,
378
368
  }
379
369
 
@@ -383,10 +373,6 @@ class TestConfiguration {
383
373
  return headers
384
374
  }
385
375
 
386
- getTenantId() {
387
- return this.tenantId || TENANT_ID
388
- }
389
-
390
376
  publicHeaders({ prodApp = true } = {}) {
391
377
  const appId = prodApp ? this.prodAppId : this.appId
392
378
 
@@ -397,9 +383,7 @@ class TestConfiguration {
397
383
  headers[constants.Header.APP_ID] = appId
398
384
  }
399
385
 
400
- if (this.tenantId) {
401
- headers[constants.Header.TENANT_ID] = this.tenantId
402
- }
386
+ headers[constants.Header.TENANT_ID] = this.getTenantId()
403
387
 
404
388
  return headers
405
389
  }
@@ -413,6 +397,34 @@ class TestConfiguration {
413
397
  return this.login({ email, roleId, builder, prodApp })
414
398
  }
415
399
 
400
+ // TENANCY
401
+
402
+ tenantHost() {
403
+ const tenantId = this.getTenantId()
404
+ const platformHost = new URL(coreEnv.PLATFORM_URL).host.split(":")[0]
405
+ return `${tenantId}.${platformHost}`
406
+ }
407
+
408
+ getTenantId() {
409
+ if (!this.tenantId) {
410
+ throw new Error("no test tenant id - init has not been called")
411
+ }
412
+ return this.tenantId
413
+ }
414
+
415
+ async newTenant(appName = newid()): Promise<App> {
416
+ this.defaultUserValues = this.populateDefaultUserValues()
417
+ this.tenantId = structures.tenant.id()
418
+ this.user = await this.globalUser()
419
+ this.globalUserId = this.user._id
420
+ this.userMetadataId = generateUserMetadataID(this.globalUserId)
421
+ return this.createApp(appName)
422
+ }
423
+
424
+ doInTenant(task: any) {
425
+ return context.doInTenant(this.getTenantId(), task)
426
+ }
427
+
416
428
  // API
417
429
 
418
430
  async generateApiKey(userId = this.defaultUserValues.globalUserId) {
@@ -432,7 +444,7 @@ class TestConfiguration {
432
444
  }
433
445
 
434
446
  // APP
435
- async createApp(appName: string) {
447
+ async createApp(appName: string): Promise<App> {
436
448
  // create dev app
437
449
  // clear any old app
438
450
  this.appId = null
@@ -442,7 +454,7 @@ class TestConfiguration {
442
454
  null,
443
455
  controllers.app.create
444
456
  )
445
- this.appId = this.app.appId
457
+ this.appId = this.app?.appId!
446
458
  })
447
459
  return await context.doInAppContext(this.appId, async () => {
448
460
  // create production app
@@ -13,8 +13,6 @@ import {
13
13
 
14
14
  const { v4: uuidv4 } = require("uuid")
15
15
 
16
- export const TENANT_ID = "default"
17
-
18
16
  export function basicTable() {
19
17
  return {
20
18
  name: "TestTable",