@budibase/server 2.7.19 → 2.7.20-alpha.0

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/dist/query.js CHANGED
@@ -838,6 +838,7 @@ var init_automation2 = __esm({
838
838
  AutomationIOType2["NUMBER"] = "number";
839
839
  AutomationIOType2["ARRAY"] = "array";
840
840
  AutomationIOType2["JSON"] = "json";
841
+ AutomationIOType2["DATE"] = "date";
841
842
  return AutomationIOType2;
842
843
  })(AutomationIOType || {});
843
844
  AutomationCustomIOType = /* @__PURE__ */ ((AutomationCustomIOType2) => {
@@ -10777,7 +10778,7 @@ function lowerBuiltinRoleID(roleId1, roleId2) {
10777
10778
  }
10778
10779
  return builtinRoleToNumber(roleId1) > builtinRoleToNumber(roleId2) ? roleId2 : roleId1;
10779
10780
  }
10780
- async function getRole(roleId) {
10781
+ async function getRole(roleId, opts) {
10781
10782
  if (!roleId) {
10782
10783
  return void 0;
10783
10784
  }
@@ -10793,6 +10794,9 @@ async function getRole(roleId) {
10793
10794
  role = Object.assign(role, dbRole);
10794
10795
  role._id = getExternalRoleID(role._id);
10795
10796
  } catch (err) {
10797
+ if (!isBuiltin(roleId) && (opts == null ? void 0 : opts.defaultPublic)) {
10798
+ return cloneDeep2(BUILTIN_ROLES.PUBLIC);
10799
+ }
10796
10800
  if (Object.keys(role).length === 0) {
10797
10801
  throw err;
10798
10802
  }
@@ -11481,8 +11485,8 @@ async function preAuth(passport2, ctx, next) {
11481
11485
  callbackUrl,
11482
11486
  ssoSaveUserNoOp
11483
11487
  );
11484
- if (!ctx.query.appId || !ctx.query.datasourceId) {
11485
- ctx.throw(400, "appId and datasourceId query params not present.");
11488
+ if (!ctx.query.appId) {
11489
+ ctx.throw(400, "appId query param not present.");
11486
11490
  }
11487
11491
  return passport2.authenticate(strategy, {
11488
11492
  scope: ["profile", "email", "https://www.googleapis.com/auth/spreadsheets"],
@@ -11502,7 +11506,7 @@ async function postAuth(passport2, ctx, next) {
11502
11506
  clientSecret: config.clientSecret,
11503
11507
  callbackURL: callbackUrl
11504
11508
  },
11505
- (accessToken, refreshToken, profile, done) => {
11509
+ (accessToken, refreshToken, _profile, done) => {
11506
11510
  clearCookie(ctx, "budibase:datasourceauth" /* DatasourceAuth */);
11507
11511
  done(null, { accessToken, refreshToken });
11508
11512
  }
@@ -11510,22 +11514,14 @@ async function postAuth(passport2, ctx, next) {
11510
11514
  { successRedirect: "/", failureRedirect: "/error" },
11511
11515
  async (err, tokens) => {
11512
11516
  const baseUrl = `/builder/app/${authStateCookie.appId}/data`;
11513
- await doWithDB(authStateCookie.appId, async (db2) => {
11514
- let datasource2;
11515
- try {
11516
- datasource2 = await db2.get(authStateCookie.datasourceId);
11517
- } catch (err2) {
11518
- if (err2.status === 404) {
11519
- ctx.redirect(baseUrl);
11520
- }
11521
- }
11522
- if (!datasource2.config) {
11523
- datasource2.config = {};
11517
+ const id = newid();
11518
+ await store(
11519
+ `datasource:creation:${authStateCookie.appId}:google:${id}`,
11520
+ {
11521
+ tokens
11524
11522
  }
11525
- datasource2.config.auth = { type: "google", ...tokens };
11526
- await db2.put(datasource2);
11527
- ctx.redirect(`${baseUrl}/datasource/${authStateCookie.datasourceId}`);
11528
- });
11523
+ );
11524
+ ctx.redirect(`${baseUrl}/new?continue_google_setup=${id}`);
11529
11525
  }
11530
11526
  )(ctx, next);
11531
11527
  }
@@ -11575,16 +11571,22 @@ var encryption_exports = {};
11575
11571
  __export(encryption_exports, {
11576
11572
  SecretOption: () => SecretOption,
11577
11573
  decrypt: () => decrypt,
11574
+ decryptFile: () => decryptFile,
11578
11575
  encrypt: () => encrypt,
11576
+ encryptFile: () => encryptFile,
11579
11577
  getSecret: () => getSecret
11580
11578
  });
11581
11579
  var import_crypto = __toESM(require("crypto"));
11580
+ var import_fs2 = __toESM(require("fs"));
11581
+ var import_zlib = __toESM(require("zlib"));
11582
11582
  init_environment2();
11583
+ var import_path2 = require("path");
11583
11584
  var ALGO = "aes-256-ctr";
11584
11585
  var SEPARATOR3 = "-";
11585
11586
  var ITERATIONS = 1e4;
11586
- var RANDOM_BYTES = 16;
11587
11587
  var STRETCH_LENGTH = 32;
11588
+ var SALT_LENGTH = 16;
11589
+ var IV_LENGTH = 16;
11588
11590
  var SecretOption = /* @__PURE__ */ ((SecretOption2) => {
11589
11591
  SecretOption2["API"] = "api";
11590
11592
  SecretOption2["ENCRYPTION"] = "encryption";
@@ -11608,11 +11610,11 @@ function getSecret(secretOption) {
11608
11610
  }
11609
11611
  return secret;
11610
11612
  }
11611
- function stretchString(string, salt) {
11612
- return import_crypto.default.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512");
11613
+ function stretchString(secret, salt) {
11614
+ return import_crypto.default.pbkdf2Sync(secret, salt, ITERATIONS, STRETCH_LENGTH, "sha512");
11613
11615
  }
11614
11616
  function encrypt(input, secretOption = "api" /* API */) {
11615
- const salt = import_crypto.default.randomBytes(RANDOM_BYTES);
11617
+ const salt = import_crypto.default.randomBytes(SALT_LENGTH);
11616
11618
  const stretched = stretchString(getSecret(secretOption), salt);
11617
11619
  const cipher = import_crypto.default.createCipheriv(ALGO, stretched, salt);
11618
11620
  const base = cipher.update(input);
@@ -11629,6 +11631,87 @@ function decrypt(input, secretOption = "api" /* API */) {
11629
11631
  const final = decipher.final();
11630
11632
  return Buffer.concat([base, final]).toString();
11631
11633
  }
11634
+ async function encryptFile({ dir, filename }, secret) {
11635
+ const outputFileName = `${filename}.enc`;
11636
+ const filePath = (0, import_path2.join)(dir, filename);
11637
+ const inputFile = import_fs2.default.createReadStream(filePath);
11638
+ const outputFile = import_fs2.default.createWriteStream((0, import_path2.join)(dir, outputFileName));
11639
+ const salt = import_crypto.default.randomBytes(SALT_LENGTH);
11640
+ const iv = import_crypto.default.randomBytes(IV_LENGTH);
11641
+ const stretched = stretchString(secret, salt);
11642
+ const cipher = import_crypto.default.createCipheriv(ALGO, stretched, iv);
11643
+ outputFile.write(salt);
11644
+ outputFile.write(iv);
11645
+ inputFile.pipe(import_zlib.default.createGzip()).pipe(cipher).pipe(outputFile);
11646
+ return new Promise((r) => {
11647
+ outputFile.on("finish", () => {
11648
+ r({
11649
+ filename: outputFileName,
11650
+ dir
11651
+ });
11652
+ });
11653
+ });
11654
+ }
11655
+ async function getSaltAndIV(path2) {
11656
+ const fileStream = import_fs2.default.createReadStream(path2);
11657
+ const salt = await readBytes(fileStream, SALT_LENGTH);
11658
+ const iv = await readBytes(fileStream, IV_LENGTH);
11659
+ fileStream.close();
11660
+ return { salt, iv };
11661
+ }
11662
+ async function decryptFile(inputPath, outputPath, secret) {
11663
+ const { salt, iv } = await getSaltAndIV(inputPath);
11664
+ const inputFile = import_fs2.default.createReadStream(inputPath, {
11665
+ start: SALT_LENGTH + IV_LENGTH
11666
+ });
11667
+ const outputFile = import_fs2.default.createWriteStream(outputPath);
11668
+ const stretched = stretchString(secret, salt);
11669
+ const decipher = import_crypto.default.createDecipheriv(ALGO, stretched, iv);
11670
+ const unzip = import_zlib.default.createGunzip();
11671
+ inputFile.pipe(decipher).pipe(unzip).pipe(outputFile);
11672
+ return new Promise((res, rej) => {
11673
+ outputFile.on("finish", () => {
11674
+ outputFile.close();
11675
+ res();
11676
+ });
11677
+ inputFile.on("error", (e) => {
11678
+ outputFile.close();
11679
+ rej(e);
11680
+ });
11681
+ decipher.on("error", (e) => {
11682
+ outputFile.close();
11683
+ rej(e);
11684
+ });
11685
+ unzip.on("error", (e) => {
11686
+ outputFile.close();
11687
+ rej(e);
11688
+ });
11689
+ outputFile.on("error", (e) => {
11690
+ outputFile.close();
11691
+ rej(e);
11692
+ });
11693
+ });
11694
+ }
11695
+ function readBytes(stream3, length) {
11696
+ return new Promise((resolve3, reject) => {
11697
+ let bytesRead = 0;
11698
+ const data = [];
11699
+ stream3.on("readable", () => {
11700
+ let chunk;
11701
+ while ((chunk = stream3.read(length - bytesRead)) !== null) {
11702
+ data.push(chunk);
11703
+ bytesRead += chunk.length;
11704
+ }
11705
+ resolve3(Buffer.concat(data));
11706
+ });
11707
+ stream3.on("end", () => {
11708
+ reject(new Error("Insufficient data in the stream."));
11709
+ });
11710
+ stream3.on("error", (error) => {
11711
+ reject(error);
11712
+ });
11713
+ });
11714
+ }
11632
11715
 
11633
11716
  // ../backend-core/src/middleware/authenticated.ts
11634
11717
  init_identity();
@@ -12386,16 +12469,16 @@ var import_aws_sdk = __toESM(require("aws-sdk"));
12386
12469
  var import_stream = __toESM(require("stream"));
12387
12470
  var import_node_fetch6 = __toESM(require("node-fetch"));
12388
12471
  var import_tar_fs = __toESM(require("tar-fs"));
12389
- var import_zlib = __toESM(require("zlib"));
12472
+ var import_zlib2 = __toESM(require("zlib"));
12390
12473
  var import_util = require("util");
12391
- var import_path3 = require("path");
12392
- var import_fs3 = __toESM(require("fs"));
12474
+ var import_path4 = require("path");
12475
+ var import_fs4 = __toESM(require("fs"));
12393
12476
  init_environment2();
12394
12477
 
12395
12478
  // ../backend-core/src/objectStore/utils.ts
12396
- var import_path2 = require("path");
12479
+ var import_path3 = require("path");
12397
12480
  var import_os = require("os");
12398
- var import_fs2 = __toESM(require("fs"));
12481
+ var import_fs3 = __toESM(require("fs"));
12399
12482
  init_environment2();
12400
12483
  var ObjectStoreBuckets = {
12401
12484
  BACKUPS: environment_default2.BACKUPS_BUCKET_NAME,
@@ -12404,9 +12487,9 @@ var ObjectStoreBuckets = {
12404
12487
  GLOBAL: environment_default2.GLOBAL_BUCKET_NAME,
12405
12488
  PLUGINS: environment_default2.PLUGIN_BUCKET_NAME
12406
12489
  };
12407
- var bbTmp = (0, import_path2.join)((0, import_os.tmpdir)(), ".budibase");
12408
- if (!import_fs2.default.existsSync(bbTmp)) {
12409
- import_fs2.default.mkdirSync(bbTmp);
12490
+ var bbTmp = (0, import_path3.join)((0, import_os.tmpdir)(), ".budibase");
12491
+ if (!import_fs3.default.existsSync(bbTmp)) {
12492
+ import_fs3.default.mkdirSync(bbTmp);
12410
12493
  }
12411
12494
  function budibaseTempDir() {
12412
12495
  return bbTmp;
@@ -12494,7 +12577,7 @@ var upload = async ({
12494
12577
  metadata: metadata2
12495
12578
  }) => {
12496
12579
  const extension = filename.split(".").pop();
12497
- const fileBytes = import_fs3.default.readFileSync(path2);
12580
+ const fileBytes = import_fs4.default.readFileSync(path2);
12498
12581
  const objectStore = ObjectStore(bucketName);
12499
12582
  await makeSureBucketExists(objectStore, bucketName);
12500
12583
  let contentType = type;
@@ -12596,13 +12679,13 @@ var retrieveToTmp = async (bucketName, filepath) => {
12596
12679
  bucketName = sanitizeBucket(bucketName);
12597
12680
  filepath = sanitizeKey(filepath);
12598
12681
  const data = await retrieve(bucketName, filepath);
12599
- const outputPath = (0, import_path3.join)(budibaseTempDir(), (0, import_uuid3.v4)());
12600
- import_fs3.default.writeFileSync(outputPath, data);
12682
+ const outputPath = (0, import_path4.join)(budibaseTempDir(), (0, import_uuid3.v4)());
12683
+ import_fs4.default.writeFileSync(outputPath, data);
12601
12684
  return outputPath;
12602
12685
  };
12603
12686
  var retrieveDirectory = async (bucketName, path2) => {
12604
- let writePath = (0, import_path3.join)(budibaseTempDir(), (0, import_uuid3.v4)());
12605
- import_fs3.default.mkdirSync(writePath);
12687
+ let writePath = (0, import_path4.join)(budibaseTempDir(), (0, import_uuid3.v4)());
12688
+ import_fs4.default.mkdirSync(writePath);
12606
12689
  const objects = await listAllObjects(bucketName, path2);
12607
12690
  let fullObjects = await Promise.all(
12608
12691
  objects.map((obj) => retrieve(bucketName, obj.Key))
@@ -12614,9 +12697,9 @@ var retrieveDirectory = async (bucketName, path2) => {
12614
12697
  const possiblePath = filename.split("/");
12615
12698
  if (possiblePath.length > 1) {
12616
12699
  const dirs = possiblePath.slice(0, possiblePath.length - 1);
12617
- import_fs3.default.mkdirSync((0, import_path3.join)(writePath, ...dirs), { recursive: true });
12700
+ import_fs4.default.mkdirSync((0, import_path4.join)(writePath, ...dirs), { recursive: true });
12618
12701
  }
12619
- import_fs3.default.writeFileSync((0, import_path3.join)(writePath, ...possiblePath), data);
12702
+ import_fs4.default.writeFileSync((0, import_path4.join)(writePath, ...possiblePath), data);
12620
12703
  }
12621
12704
  return writePath;
12622
12705
  };
@@ -12670,14 +12753,14 @@ var deleteFolder = async (bucketName, folder) => {
12670
12753
  var uploadDirectory = async (bucketName, localPath, bucketPath2) => {
12671
12754
  bucketName = sanitizeBucket(bucketName);
12672
12755
  let uploads = [];
12673
- const files2 = import_fs3.default.readdirSync(localPath, { withFileTypes: true });
12756
+ const files2 = import_fs4.default.readdirSync(localPath, { withFileTypes: true });
12674
12757
  for (let file of files2) {
12675
- const path2 = sanitizeKey((0, import_path3.join)(bucketPath2, file.name));
12676
- const local = (0, import_path3.join)(localPath, file.name);
12758
+ const path2 = sanitizeKey((0, import_path4.join)(bucketPath2, file.name));
12759
+ const local = (0, import_path4.join)(localPath, file.name);
12677
12760
  if (file.isDirectory()) {
12678
12761
  uploads.push(uploadDirectory(bucketName, local, path2));
12679
12762
  } else {
12680
- uploads.push(streamUpload(bucketName, path2, import_fs3.default.createReadStream(local)));
12763
+ uploads.push(streamUpload(bucketName, path2, import_fs4.default.createReadStream(local)));
12681
12764
  }
12682
12765
  }
12683
12766
  await Promise.all(uploads);
@@ -12689,7 +12772,7 @@ var downloadTarballDirect = async (url, path2, headers = {}) => {
12689
12772
  if (!response.ok) {
12690
12773
  throw new Error(`unexpected response ${response.statusText}`);
12691
12774
  }
12692
- await streamPipeline(response.body, import_zlib.default.createUnzip(), import_tar_fs.default.extract(path2));
12775
+ await streamPipeline(response.body, import_zlib2.default.createUnzip(), import_tar_fs.default.extract(path2));
12693
12776
  };
12694
12777
  var downloadTarball = async (url, bucketName, path2) => {
12695
12778
  bucketName = sanitizeBucket(bucketName);
@@ -12698,8 +12781,8 @@ var downloadTarball = async (url, bucketName, path2) => {
12698
12781
  if (!response.ok) {
12699
12782
  throw new Error(`unexpected response ${response.statusText}`);
12700
12783
  }
12701
- const tmpPath = (0, import_path3.join)(budibaseTempDir(), path2);
12702
- await streamPipeline(response.body, import_zlib.default.createUnzip(), import_tar_fs.default.extract(tmpPath));
12784
+ const tmpPath = (0, import_path4.join)(budibaseTempDir(), path2);
12785
+ await streamPipeline(response.body, import_zlib2.default.createUnzip(), import_tar_fs.default.extract(tmpPath));
12703
12786
  if (!environment_default2.isTest() && environment_default2.SELF_HOSTED) {
12704
12787
  await uploadDirectory(bucketName, tmpPath, path2);
12705
12788
  }
@@ -14355,7 +14438,8 @@ var PostgresIntegration = class extends sql_default {
14355
14438
  try {
14356
14439
  await this.openConnection();
14357
14440
  const columnsResponse = await this.client.query(this.COLUMNS_SQL);
14358
- return columnsResponse.rows.map((row) => row.table_name);
14441
+ const names = columnsResponse.rows.map((row) => row.table_name);
14442
+ return [...new Set(names)];
14359
14443
  } finally {
14360
14444
  await this.closeConnection();
14361
14445
  }
@@ -14968,6 +15052,8 @@ var MongoIntegration = class {
14968
15052
  response.connected = true;
14969
15053
  } catch (e) {
14970
15054
  response.error = e.message;
15055
+ } finally {
15056
+ await this.client.close();
14971
15057
  }
14972
15058
  return response;
14973
15059
  }
@@ -17235,11 +17321,39 @@ var hasFilters = (query) => {
17235
17321
  // ../shared-core/src/utils.ts
17236
17322
  var utils_exports3 = {};
17237
17323
  __export(utils_exports3, {
17324
+ parallelForeach: () => parallelForeach,
17238
17325
  unreachable: () => unreachable
17239
17326
  });
17240
17327
  function unreachable(value, message = `No such case in exhaustive switch: ${value}`) {
17241
17328
  throw new Error(message);
17242
17329
  }
17330
+ async function parallelForeach(items, task, maxConcurrency) {
17331
+ const promises = [];
17332
+ let index2 = 0;
17333
+ const processItem = async (item) => {
17334
+ try {
17335
+ await task(item);
17336
+ } finally {
17337
+ processNext();
17338
+ }
17339
+ };
17340
+ const processNext = () => {
17341
+ if (index2 >= items.length) {
17342
+ return;
17343
+ }
17344
+ const item = items[index2];
17345
+ index2++;
17346
+ const promise = processItem(item);
17347
+ promises.push(promise);
17348
+ if (promises.length >= maxConcurrency) {
17349
+ Promise.race(promises).then(processNext);
17350
+ } else {
17351
+ processNext();
17352
+ }
17353
+ };
17354
+ processNext();
17355
+ await Promise.all(promises);
17356
+ }
17243
17357
 
17244
17358
  // src/integrations/googlesheets.ts
17245
17359
  var ALLOWED_TYPES = [
@@ -17268,7 +17382,7 @@ var SCHEMA12 = {
17268
17382
  },
17269
17383
  datasource: {
17270
17384
  spreadsheetId: {
17271
- display: "Google Sheet URL",
17385
+ display: "Spreadsheet URL",
17272
17386
  type: "string" /* STRING */,
17273
17387
  required: true
17274
17388
  }
@@ -17389,6 +17503,7 @@ var GoogleSheetsIntegration = class {
17389
17503
  async connect() {
17390
17504
  var _a;
17391
17505
  try {
17506
+ await setupCreationAuth(this.config);
17392
17507
  let googleConfig = await configs_exports.getGoogleDatasourceConfig();
17393
17508
  if (!googleConfig) {
17394
17509
  throw new HTTPError("Google config not found", 400);
@@ -17439,21 +17554,22 @@ var GoogleSheetsIntegration = class {
17439
17554
  return table;
17440
17555
  }
17441
17556
  async buildSchema(datasourceId, entities) {
17442
- if (!this.config.auth) {
17443
- return;
17444
- }
17445
17557
  await this.connect();
17446
17558
  const sheets = this.client.sheetsByIndex;
17447
17559
  const tables = {};
17448
- for (let sheet of sheets) {
17449
- await sheet.getRows();
17450
- const id = buildExternalTableId(datasourceId, sheet.title);
17451
- tables[sheet.title] = this.getTableSchema(
17452
- sheet.title,
17453
- sheet.headerValues,
17454
- id
17455
- );
17456
- }
17560
+ await utils_exports3.parallelForeach(
17561
+ sheets,
17562
+ async (sheet) => {
17563
+ await sheet.getRows({ limit: 0, offset: 0 });
17564
+ const id = buildExternalTableId(datasourceId, sheet.title);
17565
+ tables[sheet.title] = this.getTableSchema(
17566
+ sheet.title,
17567
+ sheet.headerValues,
17568
+ id
17569
+ );
17570
+ },
17571
+ 10
17572
+ );
17457
17573
  const final = finaliseExternalTables(tables, entities);
17458
17574
  this.tables = final.tables;
17459
17575
  this.schemaErrors = final.errors;
@@ -17699,6 +17815,16 @@ var GoogleSheetsIntegration = class {
17699
17815
  }
17700
17816
  }
17701
17817
  };
17818
+ async function setupCreationAuth(datasouce) {
17819
+ if (datasouce.continueSetupId) {
17820
+ const appId = context_exports.getAppId();
17821
+ const tokens = await cache_exports.get(
17822
+ `datasource:creation:${appId}:google:${datasouce.continueSetupId}`
17823
+ );
17824
+ datasouce.auth = tokens.tokens;
17825
+ delete datasouce.continueSetupId;
17826
+ }
17827
+ }
17702
17828
  var googlesheets_default = {
17703
17829
  schema: SCHEMA12,
17704
17830
  integration: GoogleSheetsIntegration
@@ -18477,24 +18603,24 @@ init_src();
18477
18603
  var budibaseTempDir2 = objectStore_exports2.budibaseTempDir;
18478
18604
 
18479
18605
  // src/utilities/fileSystem/app.ts
18480
- var import_path5 = require("path");
18606
+ var import_path6 = require("path");
18481
18607
 
18482
18608
  // src/utilities/fileSystem/filesystem.ts
18483
- var import_fs4 = __toESM(require("fs"));
18484
- var import_path4 = require("path");
18609
+ var import_fs5 = __toESM(require("fs"));
18610
+ var import_path5 = require("path");
18485
18611
  var import_tar = __toESM(require("tar"));
18486
18612
  var uuid2 = require("uuid/v4");
18487
- var TOP_LEVEL_PATH = environment_default.TOP_LEVEL_PATH || (0, import_path4.resolve)((0, import_path4.join)(__dirname, "..", "..", ".."));
18613
+ var TOP_LEVEL_PATH = environment_default.TOP_LEVEL_PATH || (0, import_path5.resolve)((0, import_path5.join)(__dirname, "..", "..", ".."));
18488
18614
  var streamFile = (path2) => {
18489
- return import_fs4.default.createReadStream(path2);
18615
+ return import_fs5.default.createReadStream(path2);
18490
18616
  };
18491
18617
  var createTempFolder = (item) => {
18492
- const path2 = (0, import_path4.join)(budibaseTempDir2(), item);
18618
+ const path2 = (0, import_path5.join)(budibaseTempDir2(), item);
18493
18619
  try {
18494
- if (import_fs4.default.existsSync(path2)) {
18495
- import_fs4.default.rmSync(path2, { recursive: true, force: true });
18620
+ if (import_fs5.default.existsSync(path2)) {
18621
+ import_fs5.default.rmSync(path2, { recursive: true, force: true });
18496
18622
  }
18497
- import_fs4.default.mkdirSync(path2);
18623
+ import_fs5.default.mkdirSync(path2);
18498
18624
  } catch (err) {
18499
18625
  throw new Error(`Path cannot be created: ${err.message}`);
18500
18626
  }
@@ -18508,18 +18634,18 @@ var extractTarball = async (fromFilePath, toPath) => {
18508
18634
  };
18509
18635
 
18510
18636
  // src/utilities/fileSystem/app.ts
18511
- var NODE_MODULES_PATH = (0, import_path5.join)(TOP_LEVEL_PATH, "node_modules");
18637
+ var NODE_MODULES_PATH = (0, import_path6.join)(TOP_LEVEL_PATH, "node_modules");
18512
18638
 
18513
18639
  // src/utilities/fileSystem/plugin.ts
18514
- var import_fs5 = __toESM(require("fs"));
18515
- var import_path6 = require("path");
18516
- var DATASOURCE_PATH = (0, import_path6.join)(budibaseTempDir2(), "datasource");
18517
- var AUTOMATION_PATH = (0, import_path6.join)(budibaseTempDir2(), "automation");
18640
+ var import_fs6 = __toESM(require("fs"));
18641
+ var import_path7 = require("path");
18642
+ var DATASOURCE_PATH = (0, import_path7.join)(budibaseTempDir2(), "datasource");
18643
+ var AUTOMATION_PATH = (0, import_path7.join)(budibaseTempDir2(), "automation");
18518
18644
  var getPluginMetadata = async (path2) => {
18519
18645
  let metadata2 = {};
18520
18646
  try {
18521
- const pkg2 = import_fs5.default.readFileSync((0, import_path6.join)(path2, "package.json"), "utf8");
18522
- const schema = import_fs5.default.readFileSync((0, import_path6.join)(path2, "schema.json"), "utf8");
18647
+ const pkg2 = import_fs6.default.readFileSync((0, import_path7.join)(path2, "package.json"), "utf8");
18648
+ const schema = import_fs6.default.readFileSync((0, import_path7.join)(path2, "schema.json"), "utf8");
18523
18649
  metadata2.schema = JSON.parse(schema);
18524
18650
  metadata2.package = JSON.parse(pkg2);
18525
18651
  if (!metadata2.package.name || !metadata2.package.version || !metadata2.package.description) {
@@ -18537,19 +18663,19 @@ var getPluginMetadata = async (path2) => {
18537
18663
  async function getPluginImpl(path2, plugin) {
18538
18664
  var _a;
18539
18665
  const hash3 = (_a = plugin.schema) == null ? void 0 : _a.hash;
18540
- if (!import_fs5.default.existsSync(path2)) {
18541
- import_fs5.default.mkdirSync(path2);
18666
+ if (!import_fs6.default.existsSync(path2)) {
18667
+ import_fs6.default.mkdirSync(path2);
18542
18668
  }
18543
- const filename = (0, import_path6.join)(path2, plugin.name);
18669
+ const filename = (0, import_path7.join)(path2, plugin.name);
18544
18670
  const metadataName = `${filename}.bbmetadata`;
18545
- if (import_fs5.default.existsSync(filename)) {
18546
- const currentHash = import_fs5.default.readFileSync(metadataName, "utf8");
18671
+ if (import_fs6.default.existsSync(filename)) {
18672
+ const currentHash = import_fs6.default.readFileSync(metadataName, "utf8");
18547
18673
  if (currentHash === hash3) {
18548
18674
  return require(filename);
18549
18675
  } else {
18550
18676
  console.log(`Updating plugin: ${plugin.name}`);
18551
18677
  delete require.cache[require.resolve(filename)];
18552
- import_fs5.default.unlinkSync(filename);
18678
+ import_fs6.default.unlinkSync(filename);
18553
18679
  }
18554
18680
  }
18555
18681
  const pluginKey = objectStore_exports2.getPluginJSKey(plugin);
@@ -18557,8 +18683,8 @@ async function getPluginImpl(path2, plugin) {
18557
18683
  objectStore_exports2.ObjectStoreBuckets.PLUGINS,
18558
18684
  pluginKey
18559
18685
  );
18560
- import_fs5.default.writeFileSync(filename, pluginJs);
18561
- import_fs5.default.writeFileSync(metadataName, hash3);
18686
+ import_fs6.default.writeFileSync(filename, pluginJs);
18687
+ import_fs6.default.writeFileSync(metadataName, hash3);
18562
18688
  return require(filename);
18563
18689
  }
18564
18690
  var getDatasourcePlugin = async (plugin) => {
@@ -18593,19 +18719,20 @@ var GLOBAL_DB_EXPORT_FILE = "global.txt";
18593
18719
  var STATIC_APP_FILES = ["manifest.json", "budibase-client.js"];
18594
18720
 
18595
18721
  // src/sdk/app/backups/exports.ts
18596
- var import_fs6 = __toESM(require("fs"));
18597
- var import_path7 = require("path");
18722
+ var import_fs7 = __toESM(require("fs"));
18723
+ var import_path8 = require("path");
18724
+ var import_tar2 = __toESM(require("tar"));
18598
18725
  var uuid3 = require("uuid/v4");
18599
- var tar3 = require("tar");
18600
18726
  var MemoryStream = require("memorystream");
18601
18727
  function tarFilesToTmp(tmpDir, files2) {
18602
- const exportFile = (0, import_path7.join)(budibaseTempDir2(), `${uuid3()}.tar.gz`);
18603
- tar3.create(
18728
+ const fileName = `${uuid3()}.tar.gz`;
18729
+ const exportFile = (0, import_path8.join)(budibaseTempDir2(), fileName);
18730
+ import_tar2.default.create(
18604
18731
  {
18605
18732
  sync: true,
18606
18733
  gzip: true,
18607
18734
  file: exportFile,
18608
- recursive: true,
18735
+ noDirRecurse: false,
18609
18736
  cwd: tmpDir
18610
18737
  },
18611
18738
  files2
@@ -18622,7 +18749,7 @@ async function exportDB(dbName, opts = {}) {
18622
18749
  return db_exports.doWithDB(dbName, async (db2) => {
18623
18750
  if (opts == null ? void 0 : opts.exportPath) {
18624
18751
  const path2 = opts == null ? void 0 : opts.exportPath;
18625
- const writeStream = import_fs6.default.createWriteStream(path2);
18752
+ const writeStream = import_fs7.default.createWriteStream(path2);
18626
18753
  await db2.dump(writeStream, exportOpts);
18627
18754
  return path2;
18628
18755
  } else {
@@ -18655,9 +18782,9 @@ async function exportApp(appId, config) {
18655
18782
  for (let path2 of STATIC_APP_FILES) {
18656
18783
  const contents = await objectStore_exports2.retrieve(
18657
18784
  ObjectStoreBuckets2.APPS,
18658
- (0, import_path7.join)(appPath, path2)
18785
+ (0, import_path8.join)(appPath, path2)
18659
18786
  );
18660
- import_fs6.default.writeFileSync((0, import_path7.join)(tmpPath, path2), contents);
18787
+ import_fs7.default.writeFileSync((0, import_path8.join)(tmpPath, path2), contents);
18661
18788
  }
18662
18789
  } else {
18663
18790
  tmpPath = await objectStore_exports2.retrieveDirectory(
@@ -18666,33 +18793,48 @@ async function exportApp(appId, config) {
18666
18793
  );
18667
18794
  }
18668
18795
  }
18669
- const downloadedPath = (0, import_path7.join)(tmpPath, appPath);
18670
- if (import_fs6.default.existsSync(downloadedPath)) {
18671
- const allFiles = import_fs6.default.readdirSync(downloadedPath);
18796
+ const downloadedPath = (0, import_path8.join)(tmpPath, appPath);
18797
+ if (import_fs7.default.existsSync(downloadedPath)) {
18798
+ const allFiles = import_fs7.default.readdirSync(downloadedPath);
18672
18799
  for (let file of allFiles) {
18673
- const path2 = (0, import_path7.join)(downloadedPath, file);
18674
- import_fs6.default.renameSync(path2, (0, import_path7.join)(downloadedPath, "..", file));
18800
+ const path2 = (0, import_path8.join)(downloadedPath, file);
18801
+ import_fs7.default.renameSync(path2, (0, import_path8.join)(downloadedPath, "..", file));
18675
18802
  }
18676
- import_fs6.default.rmdirSync(downloadedPath);
18803
+ import_fs7.default.rmdirSync(downloadedPath);
18677
18804
  }
18678
- const dbPath = (0, import_path7.join)(tmpPath, DB_EXPORT_FILE);
18805
+ const dbPath = (0, import_path8.join)(tmpPath, DB_EXPORT_FILE);
18679
18806
  await exportDB(appId, {
18680
18807
  filter: defineFilter(config == null ? void 0 : config.excludeRows, config == null ? void 0 : config.excludeLogs),
18681
18808
  exportPath: dbPath
18682
18809
  });
18810
+ if (config == null ? void 0 : config.encryptPassword) {
18811
+ for (let file of import_fs7.default.readdirSync(tmpPath)) {
18812
+ const path2 = (0, import_path8.join)(tmpPath, file);
18813
+ await encryption_exports.encryptFile(
18814
+ { dir: tmpPath, filename: file },
18815
+ config.encryptPassword
18816
+ );
18817
+ import_fs7.default.rmSync(path2);
18818
+ }
18819
+ }
18683
18820
  if (config == null ? void 0 : config.tar) {
18684
- const tarPath = tarFilesToTmp(tmpPath, import_fs6.default.readdirSync(tmpPath));
18685
- import_fs6.default.rmSync(tmpPath, { recursive: true, force: true });
18821
+ const tarPath = tarFilesToTmp(tmpPath, import_fs7.default.readdirSync(tmpPath));
18822
+ import_fs7.default.rmSync(tmpPath, { recursive: true, force: true });
18686
18823
  return tarPath;
18687
18824
  } else {
18688
18825
  return tmpPath;
18689
18826
  }
18690
18827
  }
18691
- async function streamExportApp(appId, excludeRows) {
18828
+ async function streamExportApp({
18829
+ appId,
18830
+ excludeRows,
18831
+ encryptPassword
18832
+ }) {
18692
18833
  const tmpPath = await exportApp(appId, {
18693
18834
  excludeRows,
18694
18835
  excludeLogs: true,
18695
- tar: true
18836
+ tar: true,
18837
+ encryptPassword
18696
18838
  });
18697
18839
  return streamFile(tmpPath);
18698
18840
  }
@@ -18706,8 +18848,8 @@ __export(imports_exports, {
18706
18848
  untarFile: () => untarFile,
18707
18849
  updateAttachmentColumns: () => updateAttachmentColumns
18708
18850
  });
18709
- var import_path8 = require("path");
18710
- var import_fs7 = __toESM(require("fs"));
18851
+ var import_path9 = require("path");
18852
+ var import_fs8 = __toESM(require("fs"));
18711
18853
  init_src();
18712
18854
  var uuid4 = require("uuid/v4");
18713
18855
  var tar4 = require("tar");
@@ -18774,16 +18916,16 @@ async function getTemplateStream(template) {
18774
18916
  throw new Error("Cannot import a non-text based file.");
18775
18917
  }
18776
18918
  if (template.file) {
18777
- return import_fs7.default.createReadStream(template.file.path);
18919
+ return import_fs8.default.createReadStream(template.file.path);
18778
18920
  } else if (template.key) {
18779
18921
  const [type, name2] = template.key.split("/");
18780
18922
  const tmpPath = await downloadTemplate(type, name2);
18781
- return import_fs7.default.createReadStream((0, import_path8.join)(tmpPath, name2, "db", "dump.txt"));
18923
+ return import_fs8.default.createReadStream((0, import_path9.join)(tmpPath, name2, "db", "dump.txt"));
18782
18924
  }
18783
18925
  }
18784
18926
  function untarFile(file) {
18785
- const tmpPath = (0, import_path8.join)(budibaseTempDir2(), uuid4());
18786
- import_fs7.default.mkdirSync(tmpPath);
18927
+ const tmpPath = (0, import_path9.join)(budibaseTempDir2(), uuid4());
18928
+ import_fs8.default.mkdirSync(tmpPath);
18787
18929
  tar4.extract({
18788
18930
  sync: true,
18789
18931
  cwd: tmpPath,
@@ -18791,31 +18933,49 @@ function untarFile(file) {
18791
18933
  });
18792
18934
  return tmpPath;
18793
18935
  }
18936
+ async function decryptFiles(path2, password) {
18937
+ try {
18938
+ for (let file of import_fs8.default.readdirSync(path2)) {
18939
+ const inputPath = (0, import_path9.join)(path2, file);
18940
+ const outputPath = inputPath.replace(/\.enc$/, "");
18941
+ await encryption_exports.decryptFile(inputPath, outputPath, password);
18942
+ import_fs8.default.rmSync(inputPath);
18943
+ }
18944
+ } catch (err) {
18945
+ if (err.message === "incorrect header check") {
18946
+ throw new Error("File cannot be imported");
18947
+ }
18948
+ throw err;
18949
+ }
18950
+ }
18794
18951
  function getGlobalDBFile(tmpPath) {
18795
- return import_fs7.default.readFileSync((0, import_path8.join)(tmpPath, GLOBAL_DB_EXPORT_FILE), "utf8");
18952
+ return import_fs8.default.readFileSync((0, import_path9.join)(tmpPath, GLOBAL_DB_EXPORT_FILE), "utf8");
18796
18953
  }
18797
18954
  function getListOfAppsInMulti(tmpPath) {
18798
- return import_fs7.default.readdirSync(tmpPath).filter((dir) => dir !== GLOBAL_DB_EXPORT_FILE);
18955
+ return import_fs8.default.readdirSync(tmpPath).filter((dir) => dir !== GLOBAL_DB_EXPORT_FILE);
18799
18956
  }
18800
18957
  async function importApp(appId, db2, template) {
18801
18958
  var _a, _b;
18802
18959
  let prodAppId = db_exports.getProdAppID(appId);
18803
18960
  let dbStream;
18804
18961
  const isTar = template.file && ((_b = (_a = template == null ? void 0 : template.file) == null ? void 0 : _a.type) == null ? void 0 : _b.endsWith("gzip"));
18805
- const isDirectory = template.file && import_fs7.default.lstatSync(template.file.path).isDirectory();
18962
+ const isDirectory = template.file && import_fs8.default.lstatSync(template.file.path).isDirectory();
18806
18963
  if (template.file && (isTar || isDirectory)) {
18807
18964
  const tmpPath = isTar ? untarFile(template.file) : template.file.path;
18808
- const contents = import_fs7.default.readdirSync(tmpPath);
18965
+ if (isTar && template.file.password) {
18966
+ await decryptFiles(tmpPath, template.file.password);
18967
+ }
18968
+ const contents = import_fs8.default.readdirSync(tmpPath);
18809
18969
  if (contents.length) {
18810
18970
  let promises = [];
18811
18971
  let excludedFiles = [GLOBAL_DB_EXPORT_FILE, DB_EXPORT_FILE];
18812
18972
  for (let filename of contents) {
18813
- const path2 = (0, import_path8.join)(tmpPath, filename);
18973
+ const path2 = (0, import_path9.join)(tmpPath, filename);
18814
18974
  if (excludedFiles.includes(filename)) {
18815
18975
  continue;
18816
18976
  }
18817
- filename = (0, import_path8.join)(prodAppId, filename);
18818
- if (import_fs7.default.lstatSync(path2).isDirectory()) {
18977
+ filename = (0, import_path9.join)(prodAppId, filename);
18978
+ if (import_fs8.default.lstatSync(path2).isDirectory()) {
18819
18979
  promises.push(
18820
18980
  objectStore_exports2.uploadDirectory(ObjectStoreBuckets2.APPS, path2, filename)
18821
18981
  );
@@ -18831,7 +18991,7 @@ async function importApp(appId, db2, template) {
18831
18991
  }
18832
18992
  await Promise.all(promises);
18833
18993
  }
18834
- dbStream = import_fs7.default.createReadStream((0, import_path8.join)(tmpPath, DB_EXPORT_FILE));
18994
+ dbStream = import_fs8.default.createReadStream((0, import_path9.join)(tmpPath, DB_EXPORT_FILE));
18835
18995
  } else {
18836
18996
  dbStream = await getTemplateStream(template);
18837
18997
  }
@@ -19950,17 +20110,17 @@ __export(version_exports, {
19950
20110
  getLicenseVersion: () => getLicenseVersion,
19951
20111
  getProVersion: () => getProVersion
19952
20112
  });
19953
- var import_fs8 = __toESM(require("fs"));
19954
- var import_path9 = __toESM(require("path"));
20113
+ var import_fs9 = __toESM(require("fs"));
20114
+ var import_path10 = __toESM(require("path"));
19955
20115
  var getLicenseVersion = () => {
19956
20116
  if (environment_default2.isDev()) {
19957
20117
  const DEV_VER_FILENAME = "dev-version.txt";
19958
- const verFile = import_path9.default.join(objectStore_exports2.budibaseTempDir(), DEV_VER_FILENAME);
19959
- if (import_fs8.default.existsSync(verFile)) {
19960
- return import_fs8.default.readFileSync(verFile, "utf8");
20118
+ const verFile = import_path10.default.join(objectStore_exports2.budibaseTempDir(), DEV_VER_FILENAME);
20119
+ if (import_fs9.default.existsSync(verFile)) {
20120
+ return import_fs9.default.readFileSync(verFile, "utf8");
19961
20121
  } else {
19962
20122
  const devVer = utils_exports2.newid();
19963
- import_fs8.default.writeFileSync(verFile, devVer);
20123
+ import_fs9.default.writeFileSync(verFile, devVer);
19964
20124
  return devVer;
19965
20125
  }
19966
20126
  } else {
@@ -20319,16 +20479,16 @@ __export(offline_exports, {
20319
20479
  getOfflineLicense: () => getOfflineLicense,
20320
20480
  writeOfflineLicenseToDisk: () => writeOfflineLicenseToDisk
20321
20481
  });
20322
- var import_fs9 = __toESM(require("fs"));
20323
- var import_path10 = require("path");
20482
+ var import_fs10 = __toESM(require("fs"));
20483
+ var import_path11 = require("path");
20324
20484
  var import_os2 = require("os");
20325
20485
  var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
20326
20486
  var SUB_DIRECTORY = environment_default2.isTest() ? ".budibase-test" : ".budibase";
20327
- var DIRECTORY = (0, import_path10.join)((0, import_os2.tmpdir)(), SUB_DIRECTORY);
20487
+ var DIRECTORY = (0, import_path11.join)((0, import_os2.tmpdir)(), SUB_DIRECTORY);
20328
20488
  var OFFLINE_LICENSE_FILE = "offline_license.txt";
20329
- var LICENSE_FILE_PATH = (0, import_path10.join)(DIRECTORY, OFFLINE_LICENSE_FILE);
20330
- if (!import_fs9.default.existsSync(DIRECTORY)) {
20331
- import_fs9.default.mkdirSync(DIRECTORY);
20489
+ var LICENSE_FILE_PATH = (0, import_path11.join)(DIRECTORY, OFFLINE_LICENSE_FILE);
20490
+ if (!import_fs10.default.existsSync(DIRECTORY)) {
20491
+ import_fs10.default.mkdirSync(DIRECTORY);
20332
20492
  }
20333
20493
  var PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvz3jePLCFBXZ19c8Dpkv\nXtSgOhKFOcvQdo/LV0KJRUzQWDPWuO4ILtBtnqhjtIzZH4CH0qCYBet5L6Qr4CM1\nl2HXiAD1Q2rlHNW9wDaYyKb1F5f+v4RyqCAyzlkwRdksmkLeECTboojNnmRCrE3C\n8suunQP5bEScqEY2kclqzSf8e6xqMzPUg3mL/pNa1iEv7TuLbU9nJfgR36l0WmZY\n94fWnSaT8OSXSqcxsaByf06gfS3HAoTJNc7eqz1Hf9fUORQGPUAnFK8cT3SfdA36\nd/o3ZWE1TTj1zYwlCLN5qRKr3hU8nC3xEYNEbkB9SfTRaOq9Q7P8WmfLkoCPm3pR\nmwIDAQAB\n-----END PUBLIC KEY-----\n";
20334
20494
  function getOfflineLicense() {
@@ -20339,16 +20499,16 @@ function getOfflineLicense() {
20339
20499
  }
20340
20500
  }
20341
20501
  function getOfflineLicenseFromDisk() {
20342
- if (import_fs9.default.existsSync(LICENSE_FILE_PATH)) {
20343
- const token = import_fs9.default.readFileSync(LICENSE_FILE_PATH, { encoding: "utf-8" });
20502
+ if (import_fs10.default.existsSync(LICENSE_FILE_PATH)) {
20503
+ const token = import_fs10.default.readFileSync(LICENSE_FILE_PATH, { encoding: "utf-8" });
20344
20504
  return import_jsonwebtoken.default.verify(token, PUBLIC_KEY, { algorithms: ["RS256"] });
20345
20505
  }
20346
20506
  }
20347
20507
  function writeOfflineLicenseToDisk(signedLicense) {
20348
- import_fs9.default.writeFileSync(LICENSE_FILE_PATH, signedLicense, { encoding: "utf-8" });
20508
+ import_fs10.default.writeFileSync(LICENSE_FILE_PATH, signedLicense, { encoding: "utf-8" });
20349
20509
  }
20350
20510
  function deleteOfflineLicense() {
20351
- import_fs9.default.rmSync(LICENSE_FILE_PATH, { force: true });
20511
+ import_fs10.default.rmSync(LICENSE_FILE_PATH, { force: true });
20352
20512
  }
20353
20513
 
20354
20514
  // ../pro/packages/pro/src/sdk/licensing/licenses/licenses.ts
@@ -21553,10 +21713,10 @@ __export(plugins_exports, {
21553
21713
  init_src();
21554
21714
 
21555
21715
  // ../pro/packages/pro/src/utilities/fileSystem.ts
21556
- var import_fs10 = __toESM(require("fs"));
21557
- var import_path11 = require("path");
21716
+ var import_fs11 = __toESM(require("fs"));
21717
+ var import_path12 = require("path");
21558
21718
  function loadJSFile(directory2, name2) {
21559
- return import_fs10.default.readFileSync((0, import_path11.join)(directory2, name2), "utf8");
21719
+ return import_fs11.default.readFileSync((0, import_path12.join)(directory2, name2), "utf8");
21560
21720
  }
21561
21721
 
21562
21722
  // ../pro/packages/pro/src/sdk/plugins/index.ts
@@ -22193,7 +22353,7 @@ __export(processing_exports, {
22193
22353
  init: () => init12
22194
22354
  });
22195
22355
  init_src();
22196
- var import_fs11 = __toESM(require("fs"));
22356
+ var import_fs12 = __toESM(require("fs"));
22197
22357
  async function init12(opts) {
22198
22358
  await getBackupQueue().process(async (job) => {
22199
22359
  const data = job.data;
@@ -22261,8 +22421,8 @@ async function runBackup(trigger, tenantId, appId, opts) {
22261
22421
  }
22262
22422
  });
22263
22423
  await updateMetadata("complete" /* COMPLETE */, { filename, contents });
22264
- if (import_fs11.default.existsSync(tarPath)) {
22265
- import_fs11.default.rmSync(tarPath);
22424
+ if (import_fs12.default.existsSync(tarPath)) {
22425
+ import_fs12.default.rmSync(tarPath);
22266
22426
  }
22267
22427
  } catch (err) {
22268
22428
  logging_exports.logAlert("App backup error", err);
@@ -22715,7 +22875,7 @@ router3.post(
22715
22875
 
22716
22876
  // ../pro/packages/pro/src/api/controllers/apps/backups.ts
22717
22877
  init_src();
22718
- var import_fs12 = __toESM(require("fs"));
22878
+ var import_fs13 = __toESM(require("fs"));
22719
22879
  async function checkAppID(ctx, appId) {
22720
22880
  if (!await utils_exports5.appExists(appId)) {
22721
22881
  ctx.throw(400, `Provided app ID: ${appId} - is invalid.`);
@@ -22801,7 +22961,7 @@ async function downloadBackup(ctx) {
22801
22961
  const backupId = ctx.params.backupId;
22802
22962
  const { metadata: metadata2, path: path2 } = await backups_default2.downloadAppBackup(backupId);
22803
22963
  ctx.attachment(`backup-${metadata2.timestamp}.tar.gz`);
22804
- ctx.body = import_fs12.default.createReadStream(path2);
22964
+ ctx.body = import_fs13.default.createReadStream(path2);
22805
22965
  }
22806
22966
 
22807
22967
  // ../pro/packages/pro/src/api/routes/apps/backups.ts