@budibase/backend-core 2.11.42 → 2.11.44

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.
Files changed (38) hide show
  1. package/dist/index.js +652 -587
  2. package/dist/index.js.map +3 -3
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +4 -4
  5. package/dist/plugins.js.map +1 -1
  6. package/dist/plugins.js.meta.json +1 -1
  7. package/dist/src/environment.js +2 -2
  8. package/dist/src/environment.js.map +1 -1
  9. package/dist/src/objectStore/buckets/app.d.ts +7 -10
  10. package/dist/src/objectStore/buckets/app.js +40 -27
  11. package/dist/src/objectStore/buckets/app.js.map +1 -1
  12. package/dist/src/objectStore/buckets/plugins.d.ts +4 -4
  13. package/dist/src/objectStore/buckets/plugins.js +19 -19
  14. package/dist/src/objectStore/buckets/plugins.js.map +1 -1
  15. package/dist/src/objectStore/objectStore.d.ts +19 -16
  16. package/dist/src/objectStore/objectStore.js +257 -218
  17. package/dist/src/objectStore/objectStore.js.map +1 -1
  18. package/dist/src/users/users.d.ts +1 -0
  19. package/dist/src/users/users.js +20 -2
  20. package/dist/src/users/users.js.map +1 -1
  21. package/dist/src/users/utils.d.ts +1 -0
  22. package/dist/src/users/utils.js +2 -1
  23. package/dist/src/users/utils.js.map +1 -1
  24. package/dist/tests/core/utilities/structures/licenses.js +5 -0
  25. package/dist/tests/core/utilities/structures/licenses.js.map +1 -1
  26. package/dist/tests/core/utilities/structures/quotas.d.ts +1 -1
  27. package/dist/tests/core/utilities/structures/quotas.js +3 -2
  28. package/dist/tests/core/utilities/structures/quotas.js.map +1 -1
  29. package/package.json +4 -4
  30. package/src/environment.ts +2 -2
  31. package/src/objectStore/buckets/app.ts +36 -23
  32. package/src/objectStore/buckets/plugins.ts +8 -8
  33. package/src/objectStore/buckets/tests/app.spec.ts +16 -26
  34. package/src/objectStore/objectStore.ts +38 -24
  35. package/src/users/users.ts +15 -1
  36. package/src/users/utils.ts +1 -0
  37. package/tests/core/utilities/structures/licenses.ts +5 -0
  38. package/tests/core/utilities/structures/quotas.ts +3 -2
package/dist/index.js CHANGED
@@ -1753,11 +1753,11 @@ function getPackageJsonFields() {
1753
1753
  const content = (0, import_fs.readFileSync)(packageJsonFile, "utf-8");
1754
1754
  const parsedContent = JSON.parse(content);
1755
1755
  return {
1756
- VERSION: parsedContent.version,
1756
+ VERSION: process.env.BUDIBASE_VERSION || parsedContent.version,
1757
1757
  SERVICE_NAME: parsedContent.name
1758
1758
  };
1759
1759
  } catch {
1760
- return { VERSION: "", SERVICE_NAME: "" };
1760
+ return { VERSION: process.env.BUDIBASE_VERSION || "", SERVICE_NAME: "" };
1761
1761
  }
1762
1762
  }
1763
1763
  function isWorker() {
@@ -2141,8 +2141,8 @@ var init_pouchDB = __esm({
2141
2141
  import_pouchdb.default.adapter("writableStream", replicationStream.adapters.writableStream);
2142
2142
  }
2143
2143
  if (opts.find) {
2144
- const find = require("pouchdb-find");
2145
- import_pouchdb.default.plugin(find);
2144
+ const find2 = require("pouchdb-find");
2145
+ import_pouchdb.default.plugin(find2);
2146
2146
  }
2147
2147
  return import_pouchdb.default.defaults(POUCH_DB_DEFAULTS);
2148
2148
  };
@@ -2581,12 +2581,12 @@ function getAppId() {
2581
2581
  return foundId;
2582
2582
  }
2583
2583
  }
2584
- function doInEnvironmentContext(values, task) {
2585
- if (!values) {
2584
+ function doInEnvironmentContext(values2, task) {
2585
+ if (!values2) {
2586
2586
  throw new Error("Must supply environment variables.");
2587
2587
  }
2588
2588
  const updates = {
2589
- environmentVariables: values
2589
+ environmentVariables: values2
2590
2590
  };
2591
2591
  return newContext(updates, task);
2592
2592
  }
@@ -4734,7 +4734,282 @@ function sanitizeKey(input) {
4734
4734
  function sanitizeBucket(input) {
4735
4735
  return input.replace(new RegExp(APP_DEV_PREFIX, "g"), APP_PREFIX);
4736
4736
  }
4737
- var import_aws_sdk, import_stream, import_node_fetch3, import_tar_fs, import_zlib, import_util, import_path2, import_fs3, import_uuid2, sanitize, streamPipeline, STATE, CONTENT_TYPE_MAP, STRING_CONTENT_TYPES, ObjectStore, makeSureBucketExists, upload, streamUpload, retrieve, listAllObjects, getPresignedUrl, retrieveToTmp, retrieveDirectory, deleteFile, deleteFiles, deleteFolder, uploadDirectory, downloadTarballDirect, downloadTarball;
4737
+ function ObjectStore(bucket, opts = { presigning: false }) {
4738
+ const config = {
4739
+ s3ForcePathStyle: true,
4740
+ signatureVersion: "v4",
4741
+ apiVersion: "2006-03-01",
4742
+ accessKeyId: environment_default.MINIO_ACCESS_KEY,
4743
+ secretAccessKey: environment_default.MINIO_SECRET_KEY,
4744
+ region: environment_default.AWS_REGION
4745
+ };
4746
+ if (bucket) {
4747
+ config.params = {
4748
+ Bucket: sanitizeBucket(bucket)
4749
+ };
4750
+ }
4751
+ if (environment_default.MINIO_URL) {
4752
+ if (opts.presigning && environment_default.MINIO_ENABLED) {
4753
+ config.endpoint = "minio-service";
4754
+ } else {
4755
+ config.endpoint = environment_default.MINIO_URL;
4756
+ }
4757
+ }
4758
+ return new import_aws_sdk.default.S3(config);
4759
+ }
4760
+ async function makeSureBucketExists(client, bucketName) {
4761
+ bucketName = sanitizeBucket(bucketName);
4762
+ try {
4763
+ await client.headBucket({
4764
+ Bucket: bucketName
4765
+ }).promise();
4766
+ } catch (err) {
4767
+ const promises = STATE.bucketCreationPromises;
4768
+ const doesntExist = err.statusCode === 404, noAccess = err.statusCode === 403;
4769
+ if (promises[bucketName]) {
4770
+ await promises[bucketName];
4771
+ } else if (doesntExist || noAccess) {
4772
+ if (doesntExist) {
4773
+ promises[bucketName] = client.createBucket({
4774
+ Bucket: bucketName
4775
+ }).promise();
4776
+ await promises[bucketName];
4777
+ delete promises[bucketName];
4778
+ }
4779
+ } else {
4780
+ throw new Error("Unable to write to object store bucket.");
4781
+ }
4782
+ }
4783
+ }
4784
+ async function upload({
4785
+ bucket: bucketName,
4786
+ filename,
4787
+ path: path2,
4788
+ type,
4789
+ metadata
4790
+ }) {
4791
+ const extension = filename.split(".").pop();
4792
+ const fileBytes = import_fs3.default.readFileSync(path2);
4793
+ const objectStore = ObjectStore(bucketName);
4794
+ await makeSureBucketExists(objectStore, bucketName);
4795
+ let contentType = type;
4796
+ if (!contentType) {
4797
+ contentType = extension ? CONTENT_TYPE_MAP[extension.toLowerCase()] : CONTENT_TYPE_MAP.txt;
4798
+ }
4799
+ const config = {
4800
+ // windows file paths need to be converted to forward slashes for s3
4801
+ Key: sanitizeKey(filename),
4802
+ Body: fileBytes,
4803
+ ContentType: contentType
4804
+ };
4805
+ if (metadata && typeof metadata === "object") {
4806
+ for (let key of Object.keys(metadata)) {
4807
+ if (!metadata[key] || typeof metadata[key] !== "string") {
4808
+ delete metadata[key];
4809
+ }
4810
+ }
4811
+ config.Metadata = metadata;
4812
+ }
4813
+ return objectStore.upload(config).promise();
4814
+ }
4815
+ async function streamUpload(bucketName, filename, stream2, extra = {}) {
4816
+ const objectStore = ObjectStore(bucketName);
4817
+ await makeSureBucketExists(objectStore, bucketName);
4818
+ if (filename?.endsWith(".js")) {
4819
+ extra = {
4820
+ ...extra,
4821
+ ContentType: "application/javascript"
4822
+ };
4823
+ } else if (filename?.endsWith(".svg")) {
4824
+ extra = {
4825
+ ...extra,
4826
+ ContentType: "image"
4827
+ };
4828
+ }
4829
+ const params2 = {
4830
+ Bucket: sanitizeBucket(bucketName),
4831
+ Key: sanitizeKey(filename),
4832
+ Body: stream2,
4833
+ ...extra
4834
+ };
4835
+ return objectStore.upload(params2).promise();
4836
+ }
4837
+ async function retrieve(bucketName, filepath) {
4838
+ const objectStore = ObjectStore(bucketName);
4839
+ const params2 = {
4840
+ Bucket: sanitizeBucket(bucketName),
4841
+ Key: sanitizeKey(filepath)
4842
+ };
4843
+ const response = await objectStore.getObject(params2).promise();
4844
+ if (STRING_CONTENT_TYPES.includes(response.ContentType)) {
4845
+ return response.Body.toString("utf8");
4846
+ } else {
4847
+ return response.Body;
4848
+ }
4849
+ }
4850
+ async function listAllObjects(bucketName, path2) {
4851
+ const objectStore = ObjectStore(bucketName);
4852
+ const list = (params2 = {}) => {
4853
+ return objectStore.listObjectsV2({
4854
+ ...params2,
4855
+ Bucket: sanitizeBucket(bucketName),
4856
+ Prefix: sanitizeKey(path2)
4857
+ }).promise();
4858
+ };
4859
+ let isTruncated = false, token, objects = [];
4860
+ do {
4861
+ let params2 = {};
4862
+ if (token) {
4863
+ params2.ContinuationToken = token;
4864
+ }
4865
+ const response = await list(params2);
4866
+ if (response.Contents) {
4867
+ objects = objects.concat(response.Contents);
4868
+ }
4869
+ isTruncated = !!response.IsTruncated;
4870
+ } while (isTruncated);
4871
+ return objects;
4872
+ }
4873
+ function getPresignedUrl(bucketName, key, durationSeconds = 3600) {
4874
+ const objectStore = ObjectStore(bucketName, { presigning: true });
4875
+ const params2 = {
4876
+ Bucket: sanitizeBucket(bucketName),
4877
+ Key: sanitizeKey(key),
4878
+ Expires: durationSeconds
4879
+ };
4880
+ const url = objectStore.getSignedUrl("getObject", params2);
4881
+ if (!environment_default.MINIO_ENABLED) {
4882
+ return url;
4883
+ } else {
4884
+ const signedUrl = new URL(url);
4885
+ const path2 = signedUrl.pathname;
4886
+ const query = signedUrl.search;
4887
+ return `/files/signed${path2}${query}`;
4888
+ }
4889
+ }
4890
+ async function retrieveToTmp(bucketName, filepath) {
4891
+ bucketName = sanitizeBucket(bucketName);
4892
+ filepath = sanitizeKey(filepath);
4893
+ const data = await retrieve(bucketName, filepath);
4894
+ const outputPath = (0, import_path2.join)(budibaseTempDir(), (0, import_uuid2.v4)());
4895
+ import_fs3.default.writeFileSync(outputPath, data);
4896
+ return outputPath;
4897
+ }
4898
+ async function retrieveDirectory(bucketName, path2) {
4899
+ let writePath = (0, import_path2.join)(budibaseTempDir(), (0, import_uuid2.v4)());
4900
+ import_fs3.default.mkdirSync(writePath);
4901
+ const objects = await listAllObjects(bucketName, path2);
4902
+ let fullObjects = await Promise.all(
4903
+ objects.map((obj) => retrieve(bucketName, obj.Key))
4904
+ );
4905
+ let count = 0;
4906
+ for (let obj of objects) {
4907
+ const filename = obj.Key;
4908
+ const data = fullObjects[count++];
4909
+ const possiblePath = filename.split("/");
4910
+ if (possiblePath.length > 1) {
4911
+ const dirs = possiblePath.slice(0, possiblePath.length - 1);
4912
+ import_fs3.default.mkdirSync((0, import_path2.join)(writePath, ...dirs), { recursive: true });
4913
+ }
4914
+ import_fs3.default.writeFileSync((0, import_path2.join)(writePath, ...possiblePath), data);
4915
+ }
4916
+ return writePath;
4917
+ }
4918
+ async function deleteFile(bucketName, filepath) {
4919
+ const objectStore = ObjectStore(bucketName);
4920
+ await makeSureBucketExists(objectStore, bucketName);
4921
+ const params2 = {
4922
+ Bucket: bucketName,
4923
+ Key: sanitizeKey(filepath)
4924
+ };
4925
+ return objectStore.deleteObject(params2).promise();
4926
+ }
4927
+ async function deleteFiles(bucketName, filepaths) {
4928
+ const objectStore = ObjectStore(bucketName);
4929
+ await makeSureBucketExists(objectStore, bucketName);
4930
+ const params2 = {
4931
+ Bucket: bucketName,
4932
+ Delete: {
4933
+ Objects: filepaths.map((path2) => ({ Key: sanitizeKey(path2) }))
4934
+ }
4935
+ };
4936
+ return objectStore.deleteObjects(params2).promise();
4937
+ }
4938
+ async function deleteFolder(bucketName, folder) {
4939
+ bucketName = sanitizeBucket(bucketName);
4940
+ folder = sanitizeKey(folder);
4941
+ const client = ObjectStore(bucketName);
4942
+ const listParams = {
4943
+ Bucket: bucketName,
4944
+ Prefix: folder
4945
+ };
4946
+ const existingObjectsResponse = await client.listObjects(listParams).promise();
4947
+ if (existingObjectsResponse.Contents?.length === 0) {
4948
+ return;
4949
+ }
4950
+ const deleteParams = {
4951
+ Bucket: bucketName,
4952
+ Delete: {
4953
+ Objects: []
4954
+ }
4955
+ };
4956
+ existingObjectsResponse.Contents?.forEach((content) => {
4957
+ deleteParams.Delete.Objects.push({ Key: content.Key });
4958
+ });
4959
+ const deleteResponse = await client.deleteObjects(deleteParams).promise();
4960
+ if (deleteResponse.Deleted?.length === 1e3) {
4961
+ return deleteFolder(bucketName, folder);
4962
+ }
4963
+ }
4964
+ async function uploadDirectory(bucketName, localPath, bucketPath) {
4965
+ bucketName = sanitizeBucket(bucketName);
4966
+ let uploads = [];
4967
+ const files = import_fs3.default.readdirSync(localPath, { withFileTypes: true });
4968
+ for (let file of files) {
4969
+ const path2 = sanitizeKey((0, import_path2.join)(bucketPath, file.name));
4970
+ const local = (0, import_path2.join)(localPath, file.name);
4971
+ if (file.isDirectory()) {
4972
+ uploads.push(uploadDirectory(bucketName, local, path2));
4973
+ } else {
4974
+ uploads.push(streamUpload(bucketName, path2, import_fs3.default.createReadStream(local)));
4975
+ }
4976
+ }
4977
+ await Promise.all(uploads);
4978
+ return files;
4979
+ }
4980
+ async function downloadTarballDirect(url, path2, headers = {}) {
4981
+ path2 = sanitizeKey(path2);
4982
+ const response = await (0, import_node_fetch3.default)(url, { headers });
4983
+ if (!response.ok) {
4984
+ throw new Error(`unexpected response ${response.statusText}`);
4985
+ }
4986
+ await streamPipeline(response.body, import_zlib.default.createUnzip(), import_tar_fs.default.extract(path2));
4987
+ }
4988
+ async function downloadTarball(url, bucketName, path2) {
4989
+ bucketName = sanitizeBucket(bucketName);
4990
+ path2 = sanitizeKey(path2);
4991
+ const response = await (0, import_node_fetch3.default)(url);
4992
+ if (!response.ok) {
4993
+ throw new Error(`unexpected response ${response.statusText}`);
4994
+ }
4995
+ const tmpPath = (0, import_path2.join)(budibaseTempDir(), path2);
4996
+ await streamPipeline(response.body, import_zlib.default.createUnzip(), import_tar_fs.default.extract(tmpPath));
4997
+ if (!environment_default.isTest() && environment_default.SELF_HOSTED) {
4998
+ await uploadDirectory(bucketName, tmpPath, path2);
4999
+ }
5000
+ return tmpPath;
5001
+ }
5002
+ async function getReadStream(bucketName, path2) {
5003
+ bucketName = sanitizeBucket(bucketName);
5004
+ path2 = sanitizeKey(path2);
5005
+ const client = ObjectStore(bucketName);
5006
+ const params2 = {
5007
+ Bucket: bucketName,
5008
+ Key: path2
5009
+ };
5010
+ return client.getObject(params2).createReadStream();
5011
+ }
5012
+ var import_aws_sdk, import_stream, import_node_fetch3, import_tar_fs, import_zlib, import_util, import_path2, import_fs3, import_uuid2, sanitize, streamPipeline, STATE, CONTENT_TYPE_MAP, STRING_CONTENT_TYPES;
4738
5013
  var init_objectStore = __esm({
4739
5014
  "src/objectStore/objectStore.ts"() {
4740
5015
  "use strict";
@@ -4769,271 +5044,6 @@ var init_objectStore = __esm({
4769
5044
  CONTENT_TYPE_MAP.js,
4770
5045
  CONTENT_TYPE_MAP.json
4771
5046
  ];
4772
- ObjectStore = (bucket, opts = { presigning: false }) => {
4773
- const config = {
4774
- s3ForcePathStyle: true,
4775
- signatureVersion: "v4",
4776
- apiVersion: "2006-03-01",
4777
- accessKeyId: environment_default.MINIO_ACCESS_KEY,
4778
- secretAccessKey: environment_default.MINIO_SECRET_KEY,
4779
- region: environment_default.AWS_REGION
4780
- };
4781
- if (bucket) {
4782
- config.params = {
4783
- Bucket: sanitizeBucket(bucket)
4784
- };
4785
- }
4786
- if (environment_default.MINIO_URL) {
4787
- if (opts.presigning && environment_default.MINIO_ENABLED) {
4788
- config.endpoint = "minio-service";
4789
- } else {
4790
- config.endpoint = environment_default.MINIO_URL;
4791
- }
4792
- }
4793
- return new import_aws_sdk.default.S3(config);
4794
- };
4795
- makeSureBucketExists = async (client, bucketName) => {
4796
- bucketName = sanitizeBucket(bucketName);
4797
- try {
4798
- await client.headBucket({
4799
- Bucket: bucketName
4800
- }).promise();
4801
- } catch (err) {
4802
- const promises = STATE.bucketCreationPromises;
4803
- const doesntExist = err.statusCode === 404, noAccess = err.statusCode === 403;
4804
- if (promises[bucketName]) {
4805
- await promises[bucketName];
4806
- } else if (doesntExist || noAccess) {
4807
- if (doesntExist) {
4808
- promises[bucketName] = client.createBucket({
4809
- Bucket: bucketName
4810
- }).promise();
4811
- await promises[bucketName];
4812
- delete promises[bucketName];
4813
- }
4814
- } else {
4815
- throw new Error("Unable to write to object store bucket.");
4816
- }
4817
- }
4818
- };
4819
- upload = async ({
4820
- bucket: bucketName,
4821
- filename,
4822
- path: path2,
4823
- type,
4824
- metadata
4825
- }) => {
4826
- const extension = filename.split(".").pop();
4827
- const fileBytes = import_fs3.default.readFileSync(path2);
4828
- const objectStore = ObjectStore(bucketName);
4829
- await makeSureBucketExists(objectStore, bucketName);
4830
- let contentType = type;
4831
- if (!contentType) {
4832
- contentType = extension ? CONTENT_TYPE_MAP[extension.toLowerCase()] : CONTENT_TYPE_MAP.txt;
4833
- }
4834
- const config = {
4835
- // windows file paths need to be converted to forward slashes for s3
4836
- Key: sanitizeKey(filename),
4837
- Body: fileBytes,
4838
- ContentType: contentType
4839
- };
4840
- if (metadata && typeof metadata === "object") {
4841
- for (let key of Object.keys(metadata)) {
4842
- if (!metadata[key] || typeof metadata[key] !== "string") {
4843
- delete metadata[key];
4844
- }
4845
- }
4846
- config.Metadata = metadata;
4847
- }
4848
- return objectStore.upload(config).promise();
4849
- };
4850
- streamUpload = async (bucketName, filename, stream2, extra = {}) => {
4851
- const objectStore = ObjectStore(bucketName);
4852
- await makeSureBucketExists(objectStore, bucketName);
4853
- if (filename?.endsWith(".js")) {
4854
- extra = {
4855
- ...extra,
4856
- ContentType: "application/javascript"
4857
- };
4858
- } else if (filename?.endsWith(".svg")) {
4859
- extra = {
4860
- ...extra,
4861
- ContentType: "image"
4862
- };
4863
- }
4864
- const params2 = {
4865
- Bucket: sanitizeBucket(bucketName),
4866
- Key: sanitizeKey(filename),
4867
- Body: stream2,
4868
- ...extra
4869
- };
4870
- return objectStore.upload(params2).promise();
4871
- };
4872
- retrieve = async (bucketName, filepath) => {
4873
- const objectStore = ObjectStore(bucketName);
4874
- const params2 = {
4875
- Bucket: sanitizeBucket(bucketName),
4876
- Key: sanitizeKey(filepath)
4877
- };
4878
- const response = await objectStore.getObject(params2).promise();
4879
- if (STRING_CONTENT_TYPES.includes(response.ContentType)) {
4880
- return response.Body.toString("utf8");
4881
- } else {
4882
- return response.Body;
4883
- }
4884
- };
4885
- listAllObjects = async (bucketName, path2) => {
4886
- const objectStore = ObjectStore(bucketName);
4887
- const list = (params2 = {}) => {
4888
- return objectStore.listObjectsV2({
4889
- ...params2,
4890
- Bucket: sanitizeBucket(bucketName),
4891
- Prefix: sanitizeKey(path2)
4892
- }).promise();
4893
- };
4894
- let isTruncated = false, token, objects = [];
4895
- do {
4896
- let params2 = {};
4897
- if (token) {
4898
- params2.ContinuationToken = token;
4899
- }
4900
- const response = await list(params2);
4901
- if (response.Contents) {
4902
- objects = objects.concat(response.Contents);
4903
- }
4904
- isTruncated = !!response.IsTruncated;
4905
- } while (isTruncated);
4906
- return objects;
4907
- };
4908
- getPresignedUrl = (bucketName, key, durationSeconds = 3600) => {
4909
- const objectStore = ObjectStore(bucketName, { presigning: true });
4910
- const params2 = {
4911
- Bucket: sanitizeBucket(bucketName),
4912
- Key: sanitizeKey(key),
4913
- Expires: durationSeconds
4914
- };
4915
- const url = objectStore.getSignedUrl("getObject", params2);
4916
- if (!environment_default.MINIO_ENABLED) {
4917
- return url;
4918
- } else {
4919
- const signedUrl = new URL(url);
4920
- const path2 = signedUrl.pathname;
4921
- const query = signedUrl.search;
4922
- return `/files/signed${path2}${query}`;
4923
- }
4924
- };
4925
- retrieveToTmp = async (bucketName, filepath) => {
4926
- bucketName = sanitizeBucket(bucketName);
4927
- filepath = sanitizeKey(filepath);
4928
- const data = await retrieve(bucketName, filepath);
4929
- const outputPath = (0, import_path2.join)(budibaseTempDir(), (0, import_uuid2.v4)());
4930
- import_fs3.default.writeFileSync(outputPath, data);
4931
- return outputPath;
4932
- };
4933
- retrieveDirectory = async (bucketName, path2) => {
4934
- let writePath = (0, import_path2.join)(budibaseTempDir(), (0, import_uuid2.v4)());
4935
- import_fs3.default.mkdirSync(writePath);
4936
- const objects = await listAllObjects(bucketName, path2);
4937
- let fullObjects = await Promise.all(
4938
- objects.map((obj) => retrieve(bucketName, obj.Key))
4939
- );
4940
- let count = 0;
4941
- for (let obj of objects) {
4942
- const filename = obj.Key;
4943
- const data = fullObjects[count++];
4944
- const possiblePath = filename.split("/");
4945
- if (possiblePath.length > 1) {
4946
- const dirs = possiblePath.slice(0, possiblePath.length - 1);
4947
- import_fs3.default.mkdirSync((0, import_path2.join)(writePath, ...dirs), { recursive: true });
4948
- }
4949
- import_fs3.default.writeFileSync((0, import_path2.join)(writePath, ...possiblePath), data);
4950
- }
4951
- return writePath;
4952
- };
4953
- deleteFile = async (bucketName, filepath) => {
4954
- const objectStore = ObjectStore(bucketName);
4955
- await makeSureBucketExists(objectStore, bucketName);
4956
- const params2 = {
4957
- Bucket: bucketName,
4958
- Key: sanitizeKey(filepath)
4959
- };
4960
- return objectStore.deleteObject(params2).promise();
4961
- };
4962
- deleteFiles = async (bucketName, filepaths) => {
4963
- const objectStore = ObjectStore(bucketName);
4964
- await makeSureBucketExists(objectStore, bucketName);
4965
- const params2 = {
4966
- Bucket: bucketName,
4967
- Delete: {
4968
- Objects: filepaths.map((path2) => ({ Key: sanitizeKey(path2) }))
4969
- }
4970
- };
4971
- return objectStore.deleteObjects(params2).promise();
4972
- };
4973
- deleteFolder = async (bucketName, folder) => {
4974
- bucketName = sanitizeBucket(bucketName);
4975
- folder = sanitizeKey(folder);
4976
- const client = ObjectStore(bucketName);
4977
- const listParams = {
4978
- Bucket: bucketName,
4979
- Prefix: folder
4980
- };
4981
- const existingObjectsResponse = await client.listObjects(listParams).promise();
4982
- if (existingObjectsResponse.Contents?.length === 0) {
4983
- return;
4984
- }
4985
- const deleteParams = {
4986
- Bucket: bucketName,
4987
- Delete: {
4988
- Objects: []
4989
- }
4990
- };
4991
- existingObjectsResponse.Contents?.forEach((content) => {
4992
- deleteParams.Delete.Objects.push({ Key: content.Key });
4993
- });
4994
- const deleteResponse = await client.deleteObjects(deleteParams).promise();
4995
- if (deleteResponse.Deleted?.length === 1e3) {
4996
- return deleteFolder(bucketName, folder);
4997
- }
4998
- };
4999
- uploadDirectory = async (bucketName, localPath, bucketPath) => {
5000
- bucketName = sanitizeBucket(bucketName);
5001
- let uploads = [];
5002
- const files = import_fs3.default.readdirSync(localPath, { withFileTypes: true });
5003
- for (let file of files) {
5004
- const path2 = sanitizeKey((0, import_path2.join)(bucketPath, file.name));
5005
- const local = (0, import_path2.join)(localPath, file.name);
5006
- if (file.isDirectory()) {
5007
- uploads.push(uploadDirectory(bucketName, local, path2));
5008
- } else {
5009
- uploads.push(streamUpload(bucketName, path2, import_fs3.default.createReadStream(local)));
5010
- }
5011
- }
5012
- await Promise.all(uploads);
5013
- return files;
5014
- };
5015
- downloadTarballDirect = async (url, path2, headers = {}) => {
5016
- path2 = sanitizeKey(path2);
5017
- const response = await (0, import_node_fetch3.default)(url, { headers });
5018
- if (!response.ok) {
5019
- throw new Error(`unexpected response ${response.statusText}`);
5020
- }
5021
- await streamPipeline(response.body, import_zlib.default.createUnzip(), import_tar_fs.default.extract(path2));
5022
- };
5023
- downloadTarball = async (url, bucketName, path2) => {
5024
- bucketName = sanitizeBucket(bucketName);
5025
- path2 = sanitizeKey(path2);
5026
- const response = await (0, import_node_fetch3.default)(url);
5027
- if (!response.ok) {
5028
- throw new Error(`unexpected response ${response.statusText}`);
5029
- }
5030
- const tmpPath = (0, import_path2.join)(budibaseTempDir(), path2);
5031
- await streamPipeline(response.body, import_zlib.default.createUnzip(), import_tar_fs.default.extract(tmpPath));
5032
- if (!environment_default.isTest() && environment_default.SELF_HOSTED) {
5033
- await uploadDirectory(bucketName, tmpPath, path2);
5034
- }
5035
- return tmpPath;
5036
- };
5037
5047
  }
5038
5048
  });
5039
5049
 
@@ -5079,35 +5089,51 @@ var init_cloudfront = __esm({
5079
5089
  });
5080
5090
 
5081
5091
  // src/objectStore/buckets/app.ts
5082
- var clientLibraryUrl, getAppFileUrl;
5092
+ function clientLibraryPath(appId) {
5093
+ return `${sanitizeKey(appId)}/budibase-client.js`;
5094
+ }
5095
+ function clientLibraryCDNUrl(appId, version) {
5096
+ let file = clientLibraryPath(appId);
5097
+ if (environment_default.CLOUDFRONT_CDN) {
5098
+ if (version) {
5099
+ file += `?v=${version}`;
5100
+ }
5101
+ return getUrl(file);
5102
+ } else {
5103
+ return getPresignedUrl(environment_default.APPS_BUCKET_NAME, file);
5104
+ }
5105
+ }
5106
+ function clientLibraryUrl(appId, version) {
5107
+ let tenantId, qsParams;
5108
+ try {
5109
+ tenantId = getTenantId();
5110
+ } finally {
5111
+ qsParams = {
5112
+ appId,
5113
+ version
5114
+ };
5115
+ }
5116
+ if (tenantId && tenantId !== DEFAULT_TENANT_ID) {
5117
+ qsParams.tenantId = tenantId;
5118
+ }
5119
+ return `/api/assets/client?${import_querystring.default.encode(qsParams)}`;
5120
+ }
5121
+ function getAppFileUrl(s3Key) {
5122
+ if (environment_default.CLOUDFRONT_CDN) {
5123
+ return getPresignedUrl2(s3Key);
5124
+ } else {
5125
+ return getPresignedUrl(environment_default.APPS_BUCKET_NAME, s3Key);
5126
+ }
5127
+ }
5128
+ var import_querystring;
5083
5129
  var init_app5 = __esm({
5084
5130
  "src/objectStore/buckets/app.ts"() {
5085
5131
  "use strict";
5086
5132
  init_environment2();
5087
5133
  init_objectStore();
5088
5134
  init_cloudfront();
5089
- clientLibraryUrl = (appId, version) => {
5090
- if (environment_default.isProd()) {
5091
- let file = `${sanitizeKey(appId)}/budibase-client.js`;
5092
- if (environment_default.CLOUDFRONT_CDN) {
5093
- if (version) {
5094
- file += `?v=${version}`;
5095
- }
5096
- return getUrl(file);
5097
- } else {
5098
- return getPresignedUrl(environment_default.APPS_BUCKET_NAME, file);
5099
- }
5100
- } else {
5101
- return `/api/assets/client`;
5102
- }
5103
- };
5104
- getAppFileUrl = (s3Key) => {
5105
- if (environment_default.CLOUDFRONT_CDN) {
5106
- return getPresignedUrl2(s3Key);
5107
- } else {
5108
- return getPresignedUrl(environment_default.APPS_BUCKET_NAME, s3Key);
5109
- }
5110
- };
5135
+ import_querystring = __toESM(require("querystring"));
5136
+ init_context2();
5111
5137
  }
5112
5138
  });
5113
5139
 
@@ -5143,7 +5169,59 @@ var init_global3 = __esm({
5143
5169
  });
5144
5170
 
5145
5171
  // src/objectStore/buckets/plugins.ts
5146
- var enrichPluginURLs, getPluginJSUrl, getPluginIconUrl, getPluginUrl, getPluginJSKey, getPluginIconKey, getPluginS3Key, getPluginS3Dir;
5172
+ function enrichPluginURLs(plugins) {
5173
+ if (!plugins || !plugins.length) {
5174
+ return [];
5175
+ }
5176
+ return plugins.map((plugin) => {
5177
+ const jsUrl = getPluginJSUrl(plugin);
5178
+ const iconUrl = getPluginIconUrl(plugin);
5179
+ return { ...plugin, jsUrl, iconUrl };
5180
+ });
5181
+ }
5182
+ function getPluginJSUrl(plugin) {
5183
+ const s3Key = getPluginJSKey(plugin);
5184
+ return getPluginUrl(s3Key);
5185
+ }
5186
+ function getPluginIconUrl(plugin) {
5187
+ const s3Key = getPluginIconKey(plugin);
5188
+ if (!s3Key) {
5189
+ return;
5190
+ }
5191
+ return getPluginUrl(s3Key);
5192
+ }
5193
+ function getPluginUrl(s3Key) {
5194
+ if (environment_default.CLOUDFRONT_CDN) {
5195
+ return getPresignedUrl2(s3Key);
5196
+ } else {
5197
+ return getPresignedUrl(environment_default.PLUGIN_BUCKET_NAME, s3Key);
5198
+ }
5199
+ }
5200
+ function getPluginJSKey(plugin) {
5201
+ return getPluginS3Key(plugin, "plugin.min.js");
5202
+ }
5203
+ function getPluginIconKey(plugin) {
5204
+ const iconFileName = plugin.iconUrl ? "icon.svg" : plugin.iconFileName;
5205
+ if (!iconFileName) {
5206
+ return;
5207
+ }
5208
+ return getPluginS3Key(plugin, iconFileName);
5209
+ }
5210
+ function getPluginS3Key(plugin, fileName) {
5211
+ const s3Key = getPluginS3Dir(plugin.name);
5212
+ return `${s3Key}/${fileName}`;
5213
+ }
5214
+ function getPluginS3Dir(pluginName) {
5215
+ let s3Key = `${pluginName}`;
5216
+ if (environment_default.MULTI_TENANCY) {
5217
+ const tenantId = getTenantId();
5218
+ s3Key = `${tenantId}/${s3Key}`;
5219
+ }
5220
+ if (environment_default.CLOUDFRONT_CDN) {
5221
+ s3Key = `plugins/${s3Key}`;
5222
+ }
5223
+ return s3Key;
5224
+ }
5147
5225
  var init_plugins = __esm({
5148
5226
  "src/objectStore/buckets/plugins.ts"() {
5149
5227
  "use strict";
@@ -5151,59 +5229,6 @@ var init_plugins = __esm({
5151
5229
  init_objectStore();
5152
5230
  init_context2();
5153
5231
  init_cloudfront();
5154
- enrichPluginURLs = (plugins) => {
5155
- if (!plugins || !plugins.length) {
5156
- return [];
5157
- }
5158
- return plugins.map((plugin) => {
5159
- const jsUrl = getPluginJSUrl(plugin);
5160
- const iconUrl = getPluginIconUrl(plugin);
5161
- return { ...plugin, jsUrl, iconUrl };
5162
- });
5163
- };
5164
- getPluginJSUrl = (plugin) => {
5165
- const s3Key = getPluginJSKey(plugin);
5166
- return getPluginUrl(s3Key);
5167
- };
5168
- getPluginIconUrl = (plugin) => {
5169
- const s3Key = getPluginIconKey(plugin);
5170
- if (!s3Key) {
5171
- return;
5172
- }
5173
- return getPluginUrl(s3Key);
5174
- };
5175
- getPluginUrl = (s3Key) => {
5176
- if (environment_default.CLOUDFRONT_CDN) {
5177
- return getPresignedUrl2(s3Key);
5178
- } else {
5179
- return getPresignedUrl(environment_default.PLUGIN_BUCKET_NAME, s3Key);
5180
- }
5181
- };
5182
- getPluginJSKey = (plugin) => {
5183
- return getPluginS3Key(plugin, "plugin.min.js");
5184
- };
5185
- getPluginIconKey = (plugin) => {
5186
- const iconFileName = plugin.iconUrl ? "icon.svg" : plugin.iconFileName;
5187
- if (!iconFileName) {
5188
- return;
5189
- }
5190
- return getPluginS3Key(plugin, iconFileName);
5191
- };
5192
- getPluginS3Key = (plugin, fileName) => {
5193
- const s3Key = getPluginS3Dir(plugin.name);
5194
- return `${s3Key}/${fileName}`;
5195
- };
5196
- getPluginS3Dir = (pluginName) => {
5197
- let s3Key = `${pluginName}`;
5198
- if (environment_default.MULTI_TENANCY) {
5199
- const tenantId = getTenantId();
5200
- s3Key = `${tenantId}/${s3Key}`;
5201
- }
5202
- if (environment_default.CLOUDFRONT_CDN) {
5203
- s3Key = `plugins/${s3Key}`;
5204
- }
5205
- return s3Key;
5206
- };
5207
5232
  }
5208
5233
  });
5209
5234
 
@@ -5223,6 +5248,8 @@ __export(objectStore_exports2, {
5223
5248
  ObjectStore: () => ObjectStore,
5224
5249
  ObjectStoreBuckets: () => ObjectStoreBuckets,
5225
5250
  budibaseTempDir: () => budibaseTempDir,
5251
+ clientLibraryCDNUrl: () => clientLibraryCDNUrl,
5252
+ clientLibraryPath: () => clientLibraryPath,
5226
5253
  clientLibraryUrl: () => clientLibraryUrl,
5227
5254
  deleteFile: () => deleteFile,
5228
5255
  deleteFiles: () => deleteFiles,
@@ -5237,6 +5264,7 @@ __export(objectStore_exports2, {
5237
5264
  getPluginJSKey: () => getPluginJSKey,
5238
5265
  getPluginS3Dir: () => getPluginS3Dir,
5239
5266
  getPresignedUrl: () => getPresignedUrl,
5267
+ getReadStream: () => getReadStream,
5240
5268
  listAllObjects: () => listAllObjects,
5241
5269
  makeSureBucketExists: () => makeSureBucketExists,
5242
5270
  retrieve: () => retrieve,
@@ -6254,6 +6282,7 @@ __export(users_exports3, {
6254
6282
  getAccountHolderFromUserIds: () => getAccountHolderFromUserIds,
6255
6283
  getAllUserIds: () => getAllUserIds,
6256
6284
  getById: () => getById,
6285
+ getCreatorCount: () => getCreatorCount,
6257
6286
  getExistingAccounts: () => getExistingAccounts,
6258
6287
  getExistingPlatformUsers: () => getExistingPlatformUsers,
6259
6288
  getExistingTenantUsers: () => getExistingTenantUsers,
@@ -6267,6 +6296,7 @@ __export(users_exports3, {
6267
6296
  isAdmin: () => isAdmin2,
6268
6297
  isAdminOrBuilder: () => isAdminOrBuilder2,
6269
6298
  isBuilder: () => isBuilder2,
6299
+ isCreator: () => isCreator2,
6270
6300
  isGlobalBuilder: () => isGlobalBuilder2,
6271
6301
  isSupportedUserSearch: () => isSupportedUserSearch,
6272
6302
  paginatedUsers: () => paginatedUsers,
@@ -6283,240 +6313,22 @@ init_db4();
6283
6313
  init_src();
6284
6314
  init_context2();
6285
6315
  init_context2();
6286
- function removeUserPassword(users) {
6287
- if (Array.isArray(users)) {
6288
- return users.map((user) => {
6289
- if (user) {
6290
- delete user.password;
6291
- return user;
6292
- }
6293
- });
6294
- } else if (users) {
6295
- delete users.password;
6296
- return users;
6297
- }
6298
- return users;
6299
- }
6300
- var isSupportedUserSearch = (query) => {
6301
- const allowed = [
6302
- { op: "string" /* STRING */, key: "email" },
6303
- { op: "equal" /* EQUAL */, key: "_id" }
6304
- ];
6305
- for (let [key, operation] of Object.entries(query)) {
6306
- if (typeof operation !== "object") {
6307
- return false;
6308
- }
6309
- const fields = Object.keys(operation || {});
6310
- if (fields.length === 0) {
6311
- continue;
6312
- }
6313
- const allowedOperation = allowed.find(
6314
- (allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
6315
- );
6316
- if (!allowedOperation) {
6317
- return false;
6318
- }
6319
- }
6320
- return true;
6321
- };
6322
- var bulkGetGlobalUsersById = async (userIds, opts) => {
6323
- const db = getGlobalDB();
6324
- let users = (await db.allDocs({
6325
- keys: userIds,
6326
- include_docs: true
6327
- })).rows.map((row) => row.doc);
6328
- if (opts?.cleanup) {
6329
- users = removeUserPassword(users);
6330
- }
6331
- return users;
6332
- };
6333
- var getAllUserIds = async () => {
6334
- const db = getGlobalDB();
6335
- const startKey = `${"us" /* USER */}${SEPARATOR}`;
6336
- const response = await db.allDocs({
6337
- startkey: startKey,
6338
- endkey: `${startKey}${UNICODE_MAX}`
6339
- });
6340
- return response.rows.map((row) => row.id);
6341
- };
6342
- var bulkUpdateGlobalUsers = async (users) => {
6343
- const db = getGlobalDB();
6344
- return await db.bulkDocs(users);
6345
- };
6346
- async function getById(id, opts) {
6347
- const db = getGlobalDB();
6348
- let user = await db.get(id);
6349
- if (opts?.cleanup) {
6350
- user = removeUserPassword(user);
6351
- }
6352
- return user;
6353
- }
6354
- var getGlobalUserByEmail = async (email, opts) => {
6355
- if (email == null) {
6356
- throw "Must supply an email address to view";
6357
- }
6358
- const response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
6359
- key: email.toLowerCase(),
6360
- include_docs: true
6361
- });
6362
- if (Array.isArray(response)) {
6363
- throw new Error(`Multiple users found with email address: ${email}`);
6364
- }
6365
- let user = response;
6366
- if (opts?.cleanup) {
6367
- user = removeUserPassword(user);
6368
- }
6369
- return user;
6370
- };
6371
- var searchGlobalUsersByApp = async (appId, opts, getOpts) => {
6372
- if (typeof appId !== "string") {
6373
- throw new Error("Must provide a string based app ID");
6374
- }
6375
- const params2 = getUsersByAppParams(appId, {
6376
- include_docs: true
6377
- });
6378
- params2.startkey = opts && opts.startkey ? opts.startkey : params2.startkey;
6379
- let response = await queryGlobalView("by_app" /* USER_BY_APP */, params2);
6380
- if (!response) {
6381
- response = [];
6382
- }
6383
- let users = Array.isArray(response) ? response : [response];
6384
- if (getOpts?.cleanup) {
6385
- users = removeUserPassword(users);
6386
- }
6387
- return users;
6388
- };
6389
- var searchGlobalUsersByAppAccess = async (appId, opts) => {
6390
- const roleSelector = `roles.${appId}`;
6391
- let orQuery = [
6392
- {
6393
- "builder.global": true
6394
- },
6395
- {
6396
- "admin.global": true
6397
- }
6398
- ];
6399
- if (appId) {
6400
- const roleCheck = {
6401
- [roleSelector]: {
6402
- $exists: true
6403
- }
6404
- };
6405
- orQuery.push(roleCheck);
6406
- }
6407
- let searchOptions = {
6408
- selector: {
6409
- $or: orQuery,
6410
- _id: {
6411
- $regex: "^us_"
6412
- }
6413
- },
6414
- limit: opts?.limit || 50
6415
- };
6416
- const resp = await directCouchFind(getGlobalDBName(), searchOptions);
6417
- return resp?.rows;
6418
- };
6419
- var getGlobalUserByAppPage = (appId, user) => {
6420
- if (!user) {
6421
- return;
6422
- }
6423
- return generateAppUserID(getProdAppID(appId), user._id);
6424
- };
6425
- var searchGlobalUsersByEmail = async (email, opts, getOpts) => {
6426
- if (typeof email !== "string") {
6427
- throw new Error("Must provide a string to search by");
6428
- }
6429
- const lcEmail = email.toLowerCase();
6430
- const startkey = opts && opts.startkey ? opts.startkey : lcEmail;
6431
- let response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
6432
- ...opts,
6433
- startkey,
6434
- endkey: `${lcEmail}${UNICODE_MAX}`
6435
- });
6436
- if (!response) {
6437
- response = [];
6438
- }
6439
- let users = Array.isArray(response) ? response : [response];
6440
- if (getOpts?.cleanup) {
6441
- users = removeUserPassword(users);
6442
- }
6443
- return users;
6444
- };
6445
- var PAGE_LIMIT = 8;
6446
- var paginatedUsers = async ({
6447
- bookmark,
6448
- query,
6449
- appId,
6450
- limit
6451
- } = {}) => {
6452
- const db = getGlobalDB();
6453
- const pageLimit = limit ? limit + 1 : PAGE_LIMIT + 1;
6454
- const opts = {
6455
- include_docs: true,
6456
- limit: pageLimit
6457
- };
6458
- if (bookmark) {
6459
- opts.startkey = bookmark;
6460
- }
6461
- let userList, property = "_id", getKey;
6462
- if (query?.equal?._id) {
6463
- userList = [await getById(query.equal._id)];
6464
- } else if (appId) {
6465
- userList = await searchGlobalUsersByApp(appId, opts);
6466
- getKey = (doc) => getGlobalUserByAppPage(appId, doc);
6467
- } else if (query?.string?.email) {
6468
- userList = await searchGlobalUsersByEmail(query?.string?.email, opts);
6469
- property = "email";
6470
- } else {
6471
- const response = await db.allDocs(getGlobalUserParams(null, opts));
6472
- userList = response.rows.map((row) => row.doc);
6473
- }
6474
- return pagination(userList, pageLimit, {
6475
- paginate: true,
6476
- property,
6477
- getKey
6478
- });
6479
- };
6480
- async function getUserCount() {
6481
- const response = await queryGlobalViewRaw("by_email2" /* USER_BY_EMAIL */, {
6482
- limit: 0,
6483
- // to be as fast as possible - we just want the total rows count
6484
- include_docs: false
6485
- });
6486
- return response.total_rows;
6487
- }
6488
- function removePortalUserPermissions(user) {
6489
- delete user.admin;
6490
- delete user.builder;
6491
- return user;
6492
- }
6493
- function cleanseUserObject(user, base) {
6494
- delete user.admin;
6495
- delete user.builder;
6496
- delete user.roles;
6497
- if (base) {
6498
- user.admin = base.admin;
6499
- user.builder = base.builder;
6500
- user.roles = base.roles;
6501
- }
6502
- return user;
6503
- }
6504
-
6505
- // src/users/utils.ts
6506
- init_environment2();
6507
-
6508
- // src/users/lookup.ts
6509
- init_db4();
6510
- init_constants3();
6511
- async function searchExistingEmails(emails) {
6512
- let matchedEmails = [];
6513
- const existingTenantUsers = await getExistingTenantUsers(emails);
6514
- matchedEmails.push(...existingTenantUsers.map((user) => user.email));
6515
- const existingPlatformUsers = await getExistingPlatformUsers(emails);
6516
- matchedEmails.push(...existingPlatformUsers.map((user) => user._id));
6517
- const existingAccounts = await getExistingAccounts(emails);
6518
- matchedEmails.push(...existingAccounts.map((account) => account.email));
6519
- return [...new Set(matchedEmails.map((email) => email.toLowerCase()))];
6316
+
6317
+ // src/users/utils.ts
6318
+ init_environment2();
6319
+
6320
+ // src/users/lookup.ts
6321
+ init_db4();
6322
+ init_constants3();
6323
+ async function searchExistingEmails(emails) {
6324
+ let matchedEmails = [];
6325
+ const existingTenantUsers = await getExistingTenantUsers(emails);
6326
+ matchedEmails.push(...existingTenantUsers.map((user) => user.email));
6327
+ const existingPlatformUsers = await getExistingPlatformUsers(emails);
6328
+ matchedEmails.push(...existingPlatformUsers.map((user) => user._id));
6329
+ const existingAccounts = await getExistingAccounts(emails);
6330
+ matchedEmails.push(...existingAccounts.map((account) => account.email));
6331
+ return [...new Set(matchedEmails.map((email) => email.toLowerCase()))];
6520
6332
  }
6521
6333
  async function getPlatformUser(identifier) {
6522
6334
  return await queryPlatformView("platform_users_lowercase_2" /* PLATFORM_USERS_LOWERCASE */, {
@@ -6787,14 +6599,17 @@ __export(users_exports2, {
6787
6599
  getGlobalUserID: () => getGlobalUserID,
6788
6600
  hasAdminPermissions: () => hasAdminPermissions,
6789
6601
  hasAppBuilderPermissions: () => hasAppBuilderPermissions,
6602
+ hasAppCreatorPermissions: () => hasAppCreatorPermissions,
6790
6603
  hasBuilderPermissions: () => hasBuilderPermissions,
6791
6604
  isAdmin: () => isAdmin,
6792
6605
  isAdminOrBuilder: () => isAdminOrBuilder,
6793
6606
  isAdminOrGlobalBuilder: () => isAdminOrGlobalBuilder,
6794
6607
  isBuilder: () => isBuilder,
6608
+ isCreator: () => isCreator,
6795
6609
  isGlobalBuilder: () => isGlobalBuilder
6796
6610
  });
6797
6611
  init_src();
6612
+ var _ = __toESM(require("lodash/fp"));
6798
6613
  function isBuilder(user, appId) {
6799
6614
  if (!user) {
6800
6615
  return false;
@@ -6829,6 +6644,17 @@ function hasAppBuilderPermissions(user) {
6829
6644
  const isGlobalBuilder3 = !!user.builder?.global;
6830
6645
  return !isGlobalBuilder3 && appLength != null && appLength > 0;
6831
6646
  }
6647
+ function hasAppCreatorPermissions(user) {
6648
+ if (!user) {
6649
+ return false;
6650
+ }
6651
+ return _.flow(
6652
+ _.get("roles"),
6653
+ _.values,
6654
+ _.find((x) => ["CREATOR", "ADMIN"].includes(x)),
6655
+ (x) => !!x
6656
+ )(user);
6657
+ }
6832
6658
  function hasBuilderPermissions(user) {
6833
6659
  if (!user) {
6834
6660
  return false;
@@ -6841,6 +6667,12 @@ function hasAdminPermissions(user) {
6841
6667
  }
6842
6668
  return !!user.admin?.global;
6843
6669
  }
6670
+ function isCreator(user) {
6671
+ if (!user) {
6672
+ return false;
6673
+ }
6674
+ return isGlobalBuilder(user) || hasAdminPermissions(user) || hasAppBuilderPermissions(user) || hasAppCreatorPermissions(user);
6675
+ }
6844
6676
  function getGlobalUserID(userId) {
6845
6677
  if (typeof userId !== "string") {
6846
6678
  return userId;
@@ -6900,6 +6732,7 @@ var allowSortColumnByType = {
6900
6732
  // src/users/utils.ts
6901
6733
  var isBuilder2 = sdk_exports.users.isBuilder;
6902
6734
  var isAdmin2 = sdk_exports.users.isAdmin;
6735
+ var isCreator2 = sdk_exports.users.isCreator;
6903
6736
  var isGlobalBuilder2 = sdk_exports.users.isGlobalBuilder;
6904
6737
  var isAdminOrBuilder2 = sdk_exports.users.isAdminOrBuilder;
6905
6738
  var hasAdminPermissions2 = sdk_exports.users.hasAdminPermissions;
@@ -6933,6 +6766,238 @@ async function getAccountHolderFromUserIds(userIds) {
6933
6766
  }
6934
6767
  }
6935
6768
 
6769
+ // src/users/users.ts
6770
+ function removeUserPassword(users) {
6771
+ if (Array.isArray(users)) {
6772
+ return users.map((user) => {
6773
+ if (user) {
6774
+ delete user.password;
6775
+ return user;
6776
+ }
6777
+ });
6778
+ } else if (users) {
6779
+ delete users.password;
6780
+ return users;
6781
+ }
6782
+ return users;
6783
+ }
6784
+ var isSupportedUserSearch = (query) => {
6785
+ const allowed = [
6786
+ { op: "string" /* STRING */, key: "email" },
6787
+ { op: "equal" /* EQUAL */, key: "_id" }
6788
+ ];
6789
+ for (let [key, operation] of Object.entries(query)) {
6790
+ if (typeof operation !== "object") {
6791
+ return false;
6792
+ }
6793
+ const fields = Object.keys(operation || {});
6794
+ if (fields.length === 0) {
6795
+ continue;
6796
+ }
6797
+ const allowedOperation = allowed.find(
6798
+ (allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
6799
+ );
6800
+ if (!allowedOperation) {
6801
+ return false;
6802
+ }
6803
+ }
6804
+ return true;
6805
+ };
6806
+ var bulkGetGlobalUsersById = async (userIds, opts) => {
6807
+ const db = getGlobalDB();
6808
+ let users = (await db.allDocs({
6809
+ keys: userIds,
6810
+ include_docs: true
6811
+ })).rows.map((row) => row.doc);
6812
+ if (opts?.cleanup) {
6813
+ users = removeUserPassword(users);
6814
+ }
6815
+ return users;
6816
+ };
6817
+ var getAllUserIds = async () => {
6818
+ const db = getGlobalDB();
6819
+ const startKey = `${"us" /* USER */}${SEPARATOR}`;
6820
+ const response = await db.allDocs({
6821
+ startkey: startKey,
6822
+ endkey: `${startKey}${UNICODE_MAX}`
6823
+ });
6824
+ return response.rows.map((row) => row.id);
6825
+ };
6826
+ var bulkUpdateGlobalUsers = async (users) => {
6827
+ const db = getGlobalDB();
6828
+ return await db.bulkDocs(users);
6829
+ };
6830
+ async function getById(id, opts) {
6831
+ const db = getGlobalDB();
6832
+ let user = await db.get(id);
6833
+ if (opts?.cleanup) {
6834
+ user = removeUserPassword(user);
6835
+ }
6836
+ return user;
6837
+ }
6838
+ var getGlobalUserByEmail = async (email, opts) => {
6839
+ if (email == null) {
6840
+ throw "Must supply an email address to view";
6841
+ }
6842
+ const response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
6843
+ key: email.toLowerCase(),
6844
+ include_docs: true
6845
+ });
6846
+ if (Array.isArray(response)) {
6847
+ throw new Error(`Multiple users found with email address: ${email}`);
6848
+ }
6849
+ let user = response;
6850
+ if (opts?.cleanup) {
6851
+ user = removeUserPassword(user);
6852
+ }
6853
+ return user;
6854
+ };
6855
+ var searchGlobalUsersByApp = async (appId, opts, getOpts) => {
6856
+ if (typeof appId !== "string") {
6857
+ throw new Error("Must provide a string based app ID");
6858
+ }
6859
+ const params2 = getUsersByAppParams(appId, {
6860
+ include_docs: true
6861
+ });
6862
+ params2.startkey = opts && opts.startkey ? opts.startkey : params2.startkey;
6863
+ let response = await queryGlobalView("by_app" /* USER_BY_APP */, params2);
6864
+ if (!response) {
6865
+ response = [];
6866
+ }
6867
+ let users = Array.isArray(response) ? response : [response];
6868
+ if (getOpts?.cleanup) {
6869
+ users = removeUserPassword(users);
6870
+ }
6871
+ return users;
6872
+ };
6873
+ var searchGlobalUsersByAppAccess = async (appId, opts) => {
6874
+ const roleSelector = `roles.${appId}`;
6875
+ let orQuery = [
6876
+ {
6877
+ "builder.global": true
6878
+ },
6879
+ {
6880
+ "admin.global": true
6881
+ }
6882
+ ];
6883
+ if (appId) {
6884
+ const roleCheck = {
6885
+ [roleSelector]: {
6886
+ $exists: true
6887
+ }
6888
+ };
6889
+ orQuery.push(roleCheck);
6890
+ }
6891
+ let searchOptions = {
6892
+ selector: {
6893
+ $or: orQuery,
6894
+ _id: {
6895
+ $regex: "^us_"
6896
+ }
6897
+ },
6898
+ limit: opts?.limit || 50
6899
+ };
6900
+ const resp = await directCouchFind(getGlobalDBName(), searchOptions);
6901
+ return resp?.rows;
6902
+ };
6903
+ var getGlobalUserByAppPage = (appId, user) => {
6904
+ if (!user) {
6905
+ return;
6906
+ }
6907
+ return generateAppUserID(getProdAppID(appId), user._id);
6908
+ };
6909
+ var searchGlobalUsersByEmail = async (email, opts, getOpts) => {
6910
+ if (typeof email !== "string") {
6911
+ throw new Error("Must provide a string to search by");
6912
+ }
6913
+ const lcEmail = email.toLowerCase();
6914
+ const startkey = opts && opts.startkey ? opts.startkey : lcEmail;
6915
+ let response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
6916
+ ...opts,
6917
+ startkey,
6918
+ endkey: `${lcEmail}${UNICODE_MAX}`
6919
+ });
6920
+ if (!response) {
6921
+ response = [];
6922
+ }
6923
+ let users = Array.isArray(response) ? response : [response];
6924
+ if (getOpts?.cleanup) {
6925
+ users = removeUserPassword(users);
6926
+ }
6927
+ return users;
6928
+ };
6929
+ var PAGE_LIMIT = 8;
6930
+ var paginatedUsers = async ({
6931
+ bookmark,
6932
+ query,
6933
+ appId,
6934
+ limit
6935
+ } = {}) => {
6936
+ const db = getGlobalDB();
6937
+ const pageLimit = limit ? limit + 1 : PAGE_LIMIT + 1;
6938
+ const opts = {
6939
+ include_docs: true,
6940
+ limit: pageLimit
6941
+ };
6942
+ if (bookmark) {
6943
+ opts.startkey = bookmark;
6944
+ }
6945
+ let userList, property = "_id", getKey;
6946
+ if (query?.equal?._id) {
6947
+ userList = [await getById(query.equal._id)];
6948
+ } else if (appId) {
6949
+ userList = await searchGlobalUsersByApp(appId, opts);
6950
+ getKey = (doc) => getGlobalUserByAppPage(appId, doc);
6951
+ } else if (query?.string?.email) {
6952
+ userList = await searchGlobalUsersByEmail(query?.string?.email, opts);
6953
+ property = "email";
6954
+ } else {
6955
+ const response = await db.allDocs(getGlobalUserParams(null, opts));
6956
+ userList = response.rows.map((row) => row.doc);
6957
+ }
6958
+ return pagination(userList, pageLimit, {
6959
+ paginate: true,
6960
+ property,
6961
+ getKey
6962
+ });
6963
+ };
6964
+ async function getUserCount() {
6965
+ const response = await queryGlobalViewRaw("by_email2" /* USER_BY_EMAIL */, {
6966
+ limit: 0,
6967
+ // to be as fast as possible - we just want the total rows count
6968
+ include_docs: false
6969
+ });
6970
+ return response.total_rows;
6971
+ }
6972
+ async function getCreatorCount() {
6973
+ let creators = 0;
6974
+ async function iterate(startPage) {
6975
+ const page = await paginatedUsers({ bookmark: startPage });
6976
+ creators += page.data.filter(isCreator2).length;
6977
+ if (page.hasNextPage) {
6978
+ await iterate(page.nextPage);
6979
+ }
6980
+ }
6981
+ await iterate();
6982
+ return creators;
6983
+ }
6984
+ function removePortalUserPermissions(user) {
6985
+ delete user.admin;
6986
+ delete user.builder;
6987
+ return user;
6988
+ }
6989
+ function cleanseUserObject(user, base) {
6990
+ delete user.admin;
6991
+ delete user.builder;
6992
+ delete user.roles;
6993
+ if (base) {
6994
+ user.admin = base.admin;
6995
+ user.builder = base.builder;
6996
+ user.roles = base.roles;
6997
+ }
6998
+ return user;
6999
+ }
7000
+
6936
7001
  // src/users/db.ts
6937
7002
  init_environment2();
6938
7003
 
@@ -10267,7 +10332,7 @@ async function put(db, doc, writeRateMs = DEFAULT_WRITE_RATE_MS) {
10267
10332
  }
10268
10333
  return { ok: true, id: output._id, rev: output._rev };
10269
10334
  }
10270
- async function get2(db, id) {
10335
+ async function get3(db, id) {
10271
10336
  const cache = await getCache();
10272
10337
  const cacheKey = makeCacheKey(db, id);
10273
10338
  let cacheItem = await cache.get(cacheKey);
@@ -10300,7 +10365,7 @@ var Writethrough = class {
10300
10365
  return put(this.db, doc, this.writeRateMs);
10301
10366
  }
10302
10367
  async get(id) {
10303
- return get2(this.db, id);
10368
+ return get3(this.db, id);
10304
10369
  }
10305
10370
  async remove(docOrId, rev) {
10306
10371
  return remove(this.db, docOrId, rev);
@@ -10619,7 +10684,7 @@ var DEFINITIONS = [
10619
10684
  },
10620
10685
  {
10621
10686
  type: "global" /* GLOBAL */,
10622
- name: "sync_quotas_1" /* SYNC_QUOTAS */
10687
+ name: "sync_quotas_2" /* SYNC_QUOTAS */
10623
10688
  },
10624
10689
  {
10625
10690
  type: "app" /* APP */,