@budibase/backend-core 2.33.1 → 2.33.3
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/index.js +604 -287
- package/dist/index.js.map +4 -4
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +4 -4
- package/dist/plugins.js.map +1 -1
- package/dist/plugins.js.meta.json +1 -1
- package/dist/src/context/identity.js +1 -1
- package/dist/src/context/identity.js.map +1 -1
- package/dist/src/db/couch/DatabaseImpl.js +1 -1
- package/dist/src/db/couch/DatabaseImpl.js.map +1 -1
- package/dist/src/environment.js +28 -14
- package/dist/src/environment.js.map +1 -1
- package/dist/src/features/features.d.ts +1 -0
- package/dist/src/features/features.js +4 -3
- package/dist/src/features/features.js.map +1 -1
- package/dist/src/middleware/authenticated.js +16 -8
- package/dist/src/middleware/authenticated.js.map +1 -1
- package/dist/src/security/roles.d.ts +24 -3
- package/dist/src/security/roles.js +210 -51
- package/dist/src/security/roles.js.map +1 -1
- package/dist/src/sql/sql.js +300 -183
- package/dist/src/sql/sql.js.map +1 -1
- package/dist/src/sql/sqlTable.js +4 -1
- package/dist/src/sql/sqlTable.js.map +1 -1
- package/package.json +4 -4
- package/src/context/identity.ts +1 -1
- package/src/db/couch/DatabaseImpl.ts +2 -1
- package/src/environment.ts +33 -17
- package/src/features/features.ts +4 -3
- package/src/middleware/authenticated.ts +33 -17
- package/src/security/roles.ts +238 -56
- package/src/sql/sql.ts +374 -233
- package/src/sql/sqlTable.ts +4 -1
package/dist/index.js
CHANGED
|
@@ -33554,14 +33554,14 @@ var require_putty = __commonJS({
|
|
|
33554
33554
|
var buf = rfc4253.write(key);
|
|
33555
33555
|
var comment = key.comment || "";
|
|
33556
33556
|
var b64 = buf.toString("base64");
|
|
33557
|
-
var lines =
|
|
33557
|
+
var lines = wrap2(b64, 64);
|
|
33558
33558
|
lines.unshift("Public-Lines: " + lines.length);
|
|
33559
33559
|
lines.unshift("Comment: " + comment);
|
|
33560
33560
|
lines.unshift("Encryption: none");
|
|
33561
33561
|
lines.unshift("PuTTY-User-Key-File-2: " + alg);
|
|
33562
33562
|
return Buffer2.from(lines.join("\n") + "\n");
|
|
33563
33563
|
}
|
|
33564
|
-
function
|
|
33564
|
+
function wrap2(txt, len) {
|
|
33565
33565
|
var lines = [];
|
|
33566
33566
|
var pos = 0;
|
|
33567
33567
|
while (pos < txt.length) {
|
|
@@ -49489,7 +49489,7 @@ var require_util2 = __commonJS({
|
|
|
49489
49489
|
coerceToTypes,
|
|
49490
49490
|
toHash,
|
|
49491
49491
|
getProperty,
|
|
49492
|
-
escapeQuotes,
|
|
49492
|
+
escapeQuotes: escapeQuotes2,
|
|
49493
49493
|
equal: require_fast_deep_equal(),
|
|
49494
49494
|
ucs2length: require_ucs2length(),
|
|
49495
49495
|
varOccurences,
|
|
@@ -49578,9 +49578,9 @@ var require_util2 = __commonJS({
|
|
|
49578
49578
|
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
|
|
49579
49579
|
var SINGLE_QUOTE = /'|\\/g;
|
|
49580
49580
|
function getProperty(key) {
|
|
49581
|
-
return typeof key == "number" ? "[" + key + "]" : IDENTIFIER.test(key) ? "." + key : "['" +
|
|
49581
|
+
return typeof key == "number" ? "[" + key + "]" : IDENTIFIER.test(key) ? "." + key : "['" + escapeQuotes2(key) + "']";
|
|
49582
49582
|
}
|
|
49583
|
-
function
|
|
49583
|
+
function escapeQuotes2(str) {
|
|
49584
49584
|
return str.replace(SINGLE_QUOTE, "\\$&").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\f/g, "\\f").replace(/\t/g, "\\t");
|
|
49585
49585
|
}
|
|
49586
49586
|
function varOccurences(str, dataVar) {
|
|
@@ -49615,7 +49615,7 @@ var require_util2 = __commonJS({
|
|
|
49615
49615
|
return key;
|
|
49616
49616
|
}
|
|
49617
49617
|
function toQuotedString(str) {
|
|
49618
|
-
return "'" +
|
|
49618
|
+
return "'" + escapeQuotes2(str) + "'";
|
|
49619
49619
|
}
|
|
49620
49620
|
function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
|
|
49621
49621
|
var path3 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
|
|
@@ -56189,8 +56189,8 @@ var require_oauth4 = __commonJS({
|
|
|
56189
56189
|
var sha1 = shasum.digest("hex");
|
|
56190
56190
|
return Buffer2.from(sha1, "hex").toString("base64");
|
|
56191
56191
|
};
|
|
56192
|
-
OAuth.prototype.concatParams = function(oa, sep,
|
|
56193
|
-
|
|
56192
|
+
OAuth.prototype.concatParams = function(oa, sep, wrap2) {
|
|
56193
|
+
wrap2 = wrap2 || "";
|
|
56194
56194
|
var params2 = Object.keys(oa).filter(function(i) {
|
|
56195
56195
|
return i !== "realm" && i !== "oauth_signature";
|
|
56196
56196
|
}).sort();
|
|
@@ -56199,7 +56199,7 @@ var require_oauth4 = __commonJS({
|
|
|
56199
56199
|
}
|
|
56200
56200
|
params2.push("oauth_signature");
|
|
56201
56201
|
return params2.map(function(i) {
|
|
56202
|
-
return i + "=" +
|
|
56202
|
+
return i + "=" + wrap2 + oauth.rfc3986(oa[i]) + wrap2;
|
|
56203
56203
|
}).join(sep);
|
|
56204
56204
|
};
|
|
56205
56205
|
OAuth.prototype.onRequest = function(_oauth) {
|
|
@@ -61253,7 +61253,7 @@ __export(src_exports, {
|
|
|
61253
61253
|
plugins: () => plugin_exports,
|
|
61254
61254
|
queue: () => queue_exports,
|
|
61255
61255
|
redis: () => redis_exports,
|
|
61256
|
-
roles: () =>
|
|
61256
|
+
roles: () => roles_exports2,
|
|
61257
61257
|
security: () => security_exports,
|
|
61258
61258
|
sessions: () => sessions_exports,
|
|
61259
61259
|
setEnv: () => setEnv,
|
|
@@ -62109,6 +62109,7 @@ __export(helpers_exports, {
|
|
|
62109
62109
|
getUserLabel: () => getUserLabel,
|
|
62110
62110
|
isGoogleSheets: () => isGoogleSheets,
|
|
62111
62111
|
isSQL: () => isSQL,
|
|
62112
|
+
roles: () => roles_exports,
|
|
62112
62113
|
schema: () => schema_exports,
|
|
62113
62114
|
views: () => views_exports,
|
|
62114
62115
|
withTimeout: () => withTimeout
|
|
@@ -62334,6 +62335,48 @@ function basicFields(view, opts) {
|
|
|
62334
62335
|
});
|
|
62335
62336
|
}
|
|
62336
62337
|
|
|
62338
|
+
// ../shared-core/src/helpers/roles.ts
|
|
62339
|
+
var roles_exports = {};
|
|
62340
|
+
__export(roles_exports, {
|
|
62341
|
+
checkForRoleInheritanceLoops: () => checkForRoleInheritanceLoops
|
|
62342
|
+
});
|
|
62343
|
+
function prefixForCheck(id) {
|
|
62344
|
+
return `${"role" /* ROLE */}${SEPARATOR}${id}`;
|
|
62345
|
+
}
|
|
62346
|
+
function checkForRoleInheritanceLoops(roles) {
|
|
62347
|
+
const roleMap = /* @__PURE__ */ new Map();
|
|
62348
|
+
roles.forEach((role) => {
|
|
62349
|
+
roleMap.set(role._id, role);
|
|
62350
|
+
});
|
|
62351
|
+
const checked = /* @__PURE__ */ new Set();
|
|
62352
|
+
const checking = /* @__PURE__ */ new Set();
|
|
62353
|
+
function hasLoop(roleId) {
|
|
62354
|
+
const prefixed2 = prefixForCheck(roleId);
|
|
62355
|
+
if (checking.has(roleId) || checking.has(prefixed2)) {
|
|
62356
|
+
return true;
|
|
62357
|
+
}
|
|
62358
|
+
if (checked.has(roleId) || checked.has(prefixed2)) {
|
|
62359
|
+
return false;
|
|
62360
|
+
}
|
|
62361
|
+
checking.add(roleId);
|
|
62362
|
+
const role = roleMap.get(prefixed2) || roleMap.get(roleId);
|
|
62363
|
+
if (!role) {
|
|
62364
|
+
checking.delete(roleId);
|
|
62365
|
+
return false;
|
|
62366
|
+
}
|
|
62367
|
+
const inherits = Array.isArray(role.inherits) ? role.inherits : [role.inherits];
|
|
62368
|
+
for (const inheritedId of inherits) {
|
|
62369
|
+
if (inheritedId && hasLoop(inheritedId)) {
|
|
62370
|
+
return true;
|
|
62371
|
+
}
|
|
62372
|
+
}
|
|
62373
|
+
checking.delete(roleId);
|
|
62374
|
+
checked.add(roleId);
|
|
62375
|
+
return false;
|
|
62376
|
+
}
|
|
62377
|
+
return !!roles.find((role) => hasLoop(role._id));
|
|
62378
|
+
}
|
|
62379
|
+
|
|
62337
62380
|
// ../shared-core/src/filters.ts
|
|
62338
62381
|
var import_lodash2 = require("lodash");
|
|
62339
62382
|
var HBS_REGEX = /{{([^{].*?)}}/g;
|
|
@@ -63244,6 +63287,7 @@ var allowDisplayColumnByType = {
|
|
|
63244
63287
|
["number" /* NUMBER */]: true,
|
|
63245
63288
|
["datetime" /* DATETIME */]: true,
|
|
63246
63289
|
["formula" /* FORMULA */]: true,
|
|
63290
|
+
["ai" /* AI */]: true,
|
|
63247
63291
|
["auto" /* AUTO */]: true,
|
|
63248
63292
|
["internal" /* INTERNAL */]: true,
|
|
63249
63293
|
["barcodeqr" /* BARCODEQR */]: true,
|
|
@@ -63271,6 +63315,7 @@ var allowSortColumnByType = {
|
|
|
63271
63315
|
["boolean" /* BOOLEAN */]: true,
|
|
63272
63316
|
["json" /* JSON */]: true,
|
|
63273
63317
|
["formula" /* FORMULA */]: false,
|
|
63318
|
+
["ai" /* AI */]: false,
|
|
63274
63319
|
["attachment" /* ATTACHMENTS */]: false,
|
|
63275
63320
|
["attachment_single" /* ATTACHMENT_SINGLE */]: false,
|
|
63276
63321
|
["signature_single" /* SIGNATURE_SINGLE */]: false,
|
|
@@ -63293,6 +63338,7 @@ var allowDefaultColumnByType = {
|
|
|
63293
63338
|
["bigint" /* BIGINT */]: false,
|
|
63294
63339
|
["boolean" /* BOOLEAN */]: false,
|
|
63295
63340
|
["formula" /* FORMULA */]: false,
|
|
63341
|
+
["ai" /* AI */]: false,
|
|
63296
63342
|
["attachment" /* ATTACHMENTS */]: false,
|
|
63297
63343
|
["attachment_single" /* ATTACHMENT_SINGLE */]: false,
|
|
63298
63344
|
["signature_single" /* SIGNATURE_SINGLE */]: false,
|
|
@@ -63498,7 +63544,7 @@ function doInUserContext(user, ctx, task) {
|
|
|
63498
63544
|
hostInfo: {
|
|
63499
63545
|
ipAddress: ctx.request.ip,
|
|
63500
63546
|
// filled in by koa-useragent package
|
|
63501
|
-
userAgent: ctx.userAgent.
|
|
63547
|
+
userAgent: ctx.userAgent.source
|
|
63502
63548
|
}
|
|
63503
63549
|
};
|
|
63504
63550
|
return doInIdentityContext2(userContext, task);
|
|
@@ -63560,23 +63606,35 @@ function httpLogging() {
|
|
|
63560
63606
|
return process.env.HTTP_LOGGING;
|
|
63561
63607
|
}
|
|
63562
63608
|
function getPackageJsonFields() {
|
|
63563
|
-
function
|
|
63564
|
-
|
|
63565
|
-
|
|
63566
|
-
|
|
63609
|
+
function getParentFile(file) {
|
|
63610
|
+
function findFileInAncestors(fileName, currentDir) {
|
|
63611
|
+
const filePath = `${currentDir}/${fileName}`;
|
|
63612
|
+
if ((0, import_fs.existsSync)(filePath)) {
|
|
63613
|
+
return filePath;
|
|
63614
|
+
}
|
|
63615
|
+
const parentDir = `${currentDir}/..`;
|
|
63616
|
+
if (parentDir === currentDir) {
|
|
63617
|
+
return null;
|
|
63618
|
+
}
|
|
63619
|
+
return findFileInAncestors(fileName, parentDir);
|
|
63567
63620
|
}
|
|
63568
|
-
const
|
|
63569
|
-
|
|
63570
|
-
|
|
63621
|
+
const packageJsonFile = findFileInAncestors(file, process.cwd());
|
|
63622
|
+
const content = (0, import_fs.readFileSync)(packageJsonFile, "utf-8");
|
|
63623
|
+
const parsedContent = JSON.parse(content);
|
|
63624
|
+
return parsedContent;
|
|
63625
|
+
}
|
|
63626
|
+
let localVersion;
|
|
63627
|
+
if (isDev() && !isTest()) {
|
|
63628
|
+
try {
|
|
63629
|
+
const lerna = getParentFile("lerna.json");
|
|
63630
|
+
localVersion = `${lerna.version}+local`;
|
|
63631
|
+
} catch {
|
|
63571
63632
|
}
|
|
63572
|
-
return findFileInAncestors(fileName, parentDir);
|
|
63573
63633
|
}
|
|
63574
63634
|
try {
|
|
63575
|
-
const
|
|
63576
|
-
const content = (0, import_fs.readFileSync)(packageJsonFile, "utf-8");
|
|
63577
|
-
const parsedContent = JSON.parse(content);
|
|
63635
|
+
const parsedContent = getParentFile("package.json");
|
|
63578
63636
|
return {
|
|
63579
|
-
VERSION: process.env.BUDIBASE_VERSION || parsedContent.version,
|
|
63637
|
+
VERSION: localVersion || process.env.BUDIBASE_VERSION || parsedContent.version,
|
|
63580
63638
|
SERVICE_NAME: parsedContent.name
|
|
63581
63639
|
};
|
|
63582
63640
|
} catch {
|
|
@@ -66555,7 +66613,7 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
66555
66613
|
preprocess(value, {
|
|
66556
66614
|
escape,
|
|
66557
66615
|
lowercase,
|
|
66558
|
-
wrap,
|
|
66616
|
+
wrap: wrap2,
|
|
66559
66617
|
type
|
|
66560
66618
|
} = {}) {
|
|
66561
66619
|
const hasVersion = !!this.#version;
|
|
@@ -66568,7 +66626,7 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
66568
66626
|
}
|
|
66569
66627
|
if (originalType === "string" && !isNaN(value) && !type) {
|
|
66570
66628
|
value = `"${value}"`;
|
|
66571
|
-
} else if (hasVersion &&
|
|
66629
|
+
} else if (hasVersion && wrap2) {
|
|
66572
66630
|
value = originalType === "number" ? value : `"${value}"`;
|
|
66573
66631
|
}
|
|
66574
66632
|
return value;
|
|
@@ -67726,12 +67784,13 @@ var FlagSet = class {
|
|
|
67726
67784
|
}
|
|
67727
67785
|
};
|
|
67728
67786
|
var flags = new FlagSet({
|
|
67729
|
-
DEFAULT_VALUES: Flag.boolean(environment_default.isDev()),
|
|
67730
|
-
AUTOMATION_BRANCHING: Flag.boolean(environment_default.isDev()),
|
|
67731
|
-
SQS: Flag.boolean(true),
|
|
67787
|
+
["DEFAULT_VALUES" /* DEFAULT_VALUES */]: Flag.boolean(environment_default.isDev()),
|
|
67788
|
+
["AUTOMATION_BRANCHING" /* AUTOMATION_BRANCHING */]: Flag.boolean(environment_default.isDev()),
|
|
67789
|
+
["SQS" /* SQS */]: Flag.boolean(true),
|
|
67732
67790
|
["AI_CUSTOM_CONFIGS" /* AI_CUSTOM_CONFIGS */]: Flag.boolean(environment_default.isDev()),
|
|
67733
67791
|
["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(environment_default.isDev()),
|
|
67734
|
-
["TABLES_DEFAULT_ADMIN" /* TABLES_DEFAULT_ADMIN */]: Flag.boolean(environment_default.isDev())
|
|
67792
|
+
["TABLES_DEFAULT_ADMIN" /* TABLES_DEFAULT_ADMIN */]: Flag.boolean(environment_default.isDev()),
|
|
67793
|
+
["BUDIBASE_AI" /* BUDIBASE_AI */]: Flag.boolean(environment_default.isDev())
|
|
67735
67794
|
});
|
|
67736
67795
|
|
|
67737
67796
|
// src/features/tests/utils.ts
|
|
@@ -68119,7 +68178,7 @@ var DatabaseImpl = class _DatabaseImpl {
|
|
|
68119
68178
|
});
|
|
68120
68179
|
}
|
|
68121
68180
|
async destroy() {
|
|
68122
|
-
if (await flags.isEnabled("SQS") && await this.exists(SQLITE_DESIGN_DOC_ID)) {
|
|
68181
|
+
if (await flags.isEnabled("SQS" /* SQS */) && await this.exists(SQLITE_DESIGN_DOC_ID)) {
|
|
68123
68182
|
const definition = await this.get(SQLITE_DESIGN_DOC_ID);
|
|
68124
68183
|
definition.sql.tables = {};
|
|
68125
68184
|
await this.put(definition);
|
|
@@ -69321,27 +69380,35 @@ var EmailUnavailableError = class extends Error {
|
|
|
69321
69380
|
};
|
|
69322
69381
|
|
|
69323
69382
|
// src/security/roles.ts
|
|
69324
|
-
var
|
|
69325
|
-
__export(
|
|
69383
|
+
var roles_exports2 = {};
|
|
69384
|
+
__export(roles_exports2, {
|
|
69326
69385
|
AccessController: () => AccessController,
|
|
69327
69386
|
BUILTIN_ROLE_IDS: () => BUILTIN_ROLE_IDS,
|
|
69328
|
-
Role: () =>
|
|
69387
|
+
Role: () => Role2,
|
|
69388
|
+
RoleHierarchyTraversal: () => RoleHierarchyTraversal,
|
|
69329
69389
|
RoleIDVersion: () => RoleIDVersion,
|
|
69330
69390
|
builtinRoleToNumber: () => builtinRoleToNumber,
|
|
69331
69391
|
checkForRoleResourceArray: () => checkForRoleResourceArray,
|
|
69392
|
+
compareRoleIds: () => compareRoleIds,
|
|
69393
|
+
externalRole: () => externalRole,
|
|
69394
|
+
findRole: () => findRole,
|
|
69332
69395
|
getAllRoleIds: () => getAllRoleIds,
|
|
69333
69396
|
getAllRoles: () => getAllRoles,
|
|
69334
69397
|
getBuiltinRole: () => getBuiltinRole,
|
|
69335
69398
|
getBuiltinRoles: () => getBuiltinRoles,
|
|
69336
69399
|
getDBRoleID: () => getDBRoleID,
|
|
69337
69400
|
getExternalRoleID: () => getExternalRoleID,
|
|
69401
|
+
getExternalRoleIDs: () => getExternalRoleIDs,
|
|
69338
69402
|
getRole: () => getRole,
|
|
69339
69403
|
getUserRoleHierarchy: () => getUserRoleHierarchy,
|
|
69340
69404
|
getUserRoleIdHierarchy: () => getUserRoleIdHierarchy,
|
|
69341
69405
|
isBuiltin: () => isBuiltin,
|
|
69342
69406
|
lowerBuiltinRoleID: () => lowerBuiltinRoleID,
|
|
69343
|
-
|
|
69407
|
+
prefixRoleIDNoBuiltin: () => prefixRoleIDNoBuiltin,
|
|
69408
|
+
roleToNumber: () => roleToNumber,
|
|
69409
|
+
saveRoles: () => saveRoles
|
|
69344
69410
|
});
|
|
69411
|
+
var import_semver = __toESM(require("semver"));
|
|
69345
69412
|
|
|
69346
69413
|
// src/security/permissions.ts
|
|
69347
69414
|
var permissions_exports = {};
|
|
@@ -69493,6 +69560,7 @@ var GLOBAL_BUILDER = "globalBuilder" /* GLOBAL_BUILDER */;
|
|
|
69493
69560
|
|
|
69494
69561
|
// src/security/roles.ts
|
|
69495
69562
|
var import_cloneDeep2 = __toESM(require("lodash/fp/cloneDeep"));
|
|
69563
|
+
var import_lodash4 = require("lodash");
|
|
69496
69564
|
var BUILTIN_ROLE_IDS = {
|
|
69497
69565
|
ADMIN: "ADMIN",
|
|
69498
69566
|
POWER: "POWER",
|
|
@@ -69503,19 +69571,20 @@ var BUILTIN_IDS = {
|
|
|
69503
69571
|
...BUILTIN_ROLE_IDS,
|
|
69504
69572
|
BUILDER: "BUILDER"
|
|
69505
69573
|
};
|
|
69506
|
-
var EXTERNAL_BUILTIN_ROLE_IDS = [
|
|
69507
|
-
BUILTIN_IDS.ADMIN,
|
|
69508
|
-
BUILTIN_IDS.POWER,
|
|
69509
|
-
BUILTIN_IDS.BASIC,
|
|
69510
|
-
BUILTIN_IDS.PUBLIC
|
|
69511
|
-
];
|
|
69512
69574
|
var RoleIDVersion = {
|
|
69513
69575
|
// original version, with a UUID based ID
|
|
69514
69576
|
UUID: void 0,
|
|
69515
69577
|
// new version - with name based ID
|
|
69516
69578
|
NAME: "name"
|
|
69517
69579
|
};
|
|
69518
|
-
|
|
69580
|
+
function rolesInList(roleIds, ids) {
|
|
69581
|
+
if (Array.isArray(ids)) {
|
|
69582
|
+
return ids.filter((id) => roleIds.includes(id)).length === ids.length;
|
|
69583
|
+
} else {
|
|
69584
|
+
return roleIds.includes(ids);
|
|
69585
|
+
}
|
|
69586
|
+
}
|
|
69587
|
+
var Role2 = class {
|
|
69519
69588
|
constructor(id, name, permissionId, uiMetadata) {
|
|
69520
69589
|
this.permissions = {};
|
|
69521
69590
|
this._id = id;
|
|
@@ -69525,12 +69594,57 @@ var Role = class {
|
|
|
69525
69594
|
this.version = RoleIDVersion.NAME;
|
|
69526
69595
|
}
|
|
69527
69596
|
addInheritance(inherits) {
|
|
69597
|
+
if (inherits && typeof inherits === "string") {
|
|
69598
|
+
inherits = prefixRoleIDNoBuiltin(inherits);
|
|
69599
|
+
} else if (inherits && Array.isArray(inherits)) {
|
|
69600
|
+
inherits = inherits.map(prefixRoleIDNoBuiltin);
|
|
69601
|
+
}
|
|
69528
69602
|
this.inherits = inherits;
|
|
69529
69603
|
return this;
|
|
69530
69604
|
}
|
|
69531
69605
|
};
|
|
69606
|
+
var RoleHierarchyTraversal = class {
|
|
69607
|
+
constructor(allRoles, opts) {
|
|
69608
|
+
this.allRoles = allRoles;
|
|
69609
|
+
this.opts = opts;
|
|
69610
|
+
}
|
|
69611
|
+
walk(role) {
|
|
69612
|
+
const opts = this.opts, allRoles = this.allRoles;
|
|
69613
|
+
let roleList = [];
|
|
69614
|
+
if (!role || !role._id) {
|
|
69615
|
+
return roleList;
|
|
69616
|
+
}
|
|
69617
|
+
roleList.push(role);
|
|
69618
|
+
if (Array.isArray(role.inherits)) {
|
|
69619
|
+
for (let roleId of role.inherits) {
|
|
69620
|
+
const foundRole = findRole(roleId, allRoles, opts);
|
|
69621
|
+
if (foundRole) {
|
|
69622
|
+
roleList = roleList.concat(this.walk(foundRole));
|
|
69623
|
+
}
|
|
69624
|
+
}
|
|
69625
|
+
} else {
|
|
69626
|
+
const foundRoleIds = [];
|
|
69627
|
+
let currentRole = role;
|
|
69628
|
+
while (currentRole && currentRole.inherits && !rolesInList(foundRoleIds, currentRole.inherits)) {
|
|
69629
|
+
if (Array.isArray(currentRole.inherits)) {
|
|
69630
|
+
return roleList.concat(this.walk(currentRole));
|
|
69631
|
+
} else {
|
|
69632
|
+
foundRoleIds.push(currentRole.inherits);
|
|
69633
|
+
currentRole = findRole(currentRole.inherits, allRoles, opts);
|
|
69634
|
+
if (currentRole) {
|
|
69635
|
+
roleList.push(currentRole);
|
|
69636
|
+
}
|
|
69637
|
+
}
|
|
69638
|
+
if (helpers_exports.roles.checkForRoleInheritanceLoops(roleList)) {
|
|
69639
|
+
break;
|
|
69640
|
+
}
|
|
69641
|
+
}
|
|
69642
|
+
}
|
|
69643
|
+
return (0, import_lodash4.uniqBy)(roleList, (role2) => role2._id);
|
|
69644
|
+
}
|
|
69645
|
+
};
|
|
69532
69646
|
var BUILTIN_ROLES = {
|
|
69533
|
-
ADMIN: new
|
|
69647
|
+
ADMIN: new Role2(
|
|
69534
69648
|
BUILTIN_IDS.ADMIN,
|
|
69535
69649
|
BUILTIN_IDS.ADMIN,
|
|
69536
69650
|
"admin" /* ADMIN */,
|
|
@@ -69540,7 +69654,7 @@ var BUILTIN_ROLES = {
|
|
|
69540
69654
|
color: "var(--spectrum-global-color-static-red-400)" /* ADMIN */
|
|
69541
69655
|
}
|
|
69542
69656
|
).addInheritance(BUILTIN_IDS.POWER),
|
|
69543
|
-
POWER: new
|
|
69657
|
+
POWER: new Role2(
|
|
69544
69658
|
BUILTIN_IDS.POWER,
|
|
69545
69659
|
BUILTIN_IDS.POWER,
|
|
69546
69660
|
"power" /* POWER */,
|
|
@@ -69550,7 +69664,7 @@ var BUILTIN_ROLES = {
|
|
|
69550
69664
|
color: "var(--spectrum-global-color-static-orange-400)" /* POWER */
|
|
69551
69665
|
}
|
|
69552
69666
|
).addInheritance(BUILTIN_IDS.BASIC),
|
|
69553
|
-
BASIC: new
|
|
69667
|
+
BASIC: new Role2(
|
|
69554
69668
|
BUILTIN_IDS.BASIC,
|
|
69555
69669
|
BUILTIN_IDS.BASIC,
|
|
69556
69670
|
"write" /* WRITE */,
|
|
@@ -69560,7 +69674,7 @@ var BUILTIN_ROLES = {
|
|
|
69560
69674
|
color: "var(--spectrum-global-color-static-green-400)" /* BASIC */
|
|
69561
69675
|
}
|
|
69562
69676
|
).addInheritance(BUILTIN_IDS.PUBLIC),
|
|
69563
|
-
PUBLIC: new
|
|
69677
|
+
PUBLIC: new Role2(
|
|
69564
69678
|
BUILTIN_IDS.PUBLIC,
|
|
69565
69679
|
BUILTIN_IDS.PUBLIC,
|
|
69566
69680
|
"public" /* PUBLIC */,
|
|
@@ -69570,7 +69684,7 @@ var BUILTIN_ROLES = {
|
|
|
69570
69684
|
color: "var(--spectrum-global-color-static-blue-400)" /* PUBLIC */
|
|
69571
69685
|
}
|
|
69572
69686
|
),
|
|
69573
|
-
BUILDER: new
|
|
69687
|
+
BUILDER: new Role2(
|
|
69574
69688
|
BUILTIN_IDS.BUILDER,
|
|
69575
69689
|
BUILTIN_IDS.BUILDER,
|
|
69576
69690
|
"admin" /* ADMIN */,
|
|
@@ -69585,7 +69699,14 @@ function getBuiltinRoles() {
|
|
|
69585
69699
|
return (0, import_cloneDeep2.default)(BUILTIN_ROLES);
|
|
69586
69700
|
}
|
|
69587
69701
|
function isBuiltin(role) {
|
|
69588
|
-
return
|
|
69702
|
+
return Object.values(BUILTIN_ROLE_IDS).includes(role);
|
|
69703
|
+
}
|
|
69704
|
+
function prefixRoleIDNoBuiltin(roleId) {
|
|
69705
|
+
if (isBuiltin(roleId)) {
|
|
69706
|
+
return roleId;
|
|
69707
|
+
} else {
|
|
69708
|
+
return prefixRoleID(roleId);
|
|
69709
|
+
}
|
|
69589
69710
|
}
|
|
69590
69711
|
function getBuiltinRole(roleId) {
|
|
69591
69712
|
const role = Object.values(BUILTIN_ROLES).find(
|
|
@@ -69607,7 +69728,11 @@ function builtinRoleToNumber(id) {
|
|
|
69607
69728
|
if (!role) {
|
|
69608
69729
|
break;
|
|
69609
69730
|
}
|
|
69610
|
-
|
|
69731
|
+
if (Array.isArray(role.inherits)) {
|
|
69732
|
+
throw new Error("Built-in roles don't support multi-inheritance");
|
|
69733
|
+
} else {
|
|
69734
|
+
role = builtins[role.inherits];
|
|
69735
|
+
}
|
|
69611
69736
|
count++;
|
|
69612
69737
|
} while (role !== null);
|
|
69613
69738
|
return count;
|
|
@@ -69619,12 +69744,26 @@ async function roleToNumber(id) {
|
|
|
69619
69744
|
const hierarchy = await getUserRoleHierarchy(id, {
|
|
69620
69745
|
defaultPublic: true
|
|
69621
69746
|
});
|
|
69622
|
-
|
|
69623
|
-
if (role
|
|
69747
|
+
const findNumber = (role) => {
|
|
69748
|
+
if (!role.inherits) {
|
|
69749
|
+
return 0;
|
|
69750
|
+
}
|
|
69751
|
+
if (Array.isArray(role.inherits)) {
|
|
69752
|
+
const highestBuiltin = role.inherits.map((roleId) => {
|
|
69753
|
+
const foundRole = hierarchy.find((role2) => role2._id === roleId);
|
|
69754
|
+
if (foundRole) {
|
|
69755
|
+
return findNumber(foundRole) + 1;
|
|
69756
|
+
}
|
|
69757
|
+
}).filter((number) => number).sort().pop();
|
|
69758
|
+
if (highestBuiltin != void 0) {
|
|
69759
|
+
return highestBuiltin;
|
|
69760
|
+
}
|
|
69761
|
+
} else if (isBuiltin(role.inherits)) {
|
|
69624
69762
|
return builtinRoleToNumber(role.inherits) + 1;
|
|
69625
69763
|
}
|
|
69626
|
-
|
|
69627
|
-
|
|
69764
|
+
return 0;
|
|
69765
|
+
};
|
|
69766
|
+
return Math.max(...hierarchy.map(findNumber));
|
|
69628
69767
|
}
|
|
69629
69768
|
function lowerBuiltinRoleID(roleId1, roleId2) {
|
|
69630
69769
|
if (!roleId1) {
|
|
@@ -69635,39 +69774,67 @@ function lowerBuiltinRoleID(roleId1, roleId2) {
|
|
|
69635
69774
|
}
|
|
69636
69775
|
return builtinRoleToNumber(roleId1) > builtinRoleToNumber(roleId2) ? roleId2 : roleId1;
|
|
69637
69776
|
}
|
|
69638
|
-
|
|
69777
|
+
function compareRoleIds(roleId1, roleId2) {
|
|
69778
|
+
return prefixRoleID(roleId1) === prefixRoleID(roleId2);
|
|
69779
|
+
}
|
|
69780
|
+
function externalRole(role) {
|
|
69781
|
+
let _id;
|
|
69782
|
+
if (role._id) {
|
|
69783
|
+
_id = getExternalRoleID(role._id);
|
|
69784
|
+
}
|
|
69785
|
+
return {
|
|
69786
|
+
...role,
|
|
69787
|
+
_id,
|
|
69788
|
+
inherits: getExternalRoleIDs(role.inherits, role.version)
|
|
69789
|
+
};
|
|
69790
|
+
}
|
|
69791
|
+
function findRole(roleId, roles, opts) {
|
|
69639
69792
|
let role = getBuiltinRole(roleId);
|
|
69640
69793
|
if (!role) {
|
|
69641
69794
|
roleId = prefixRoleID(roleId);
|
|
69642
69795
|
}
|
|
69643
|
-
|
|
69644
|
-
|
|
69645
|
-
|
|
69646
|
-
|
|
69796
|
+
const dbRole = roles.find(
|
|
69797
|
+
(role2) => role2._id && compareRoleIds(role2._id, roleId)
|
|
69798
|
+
);
|
|
69799
|
+
if (!dbRole && !isBuiltin(roleId) && opts?.defaultPublic) {
|
|
69800
|
+
return (0, import_cloneDeep2.default)(BUILTIN_ROLES.PUBLIC);
|
|
69801
|
+
}
|
|
69802
|
+
role = Object.assign(role || {}, dbRole);
|
|
69803
|
+
if (role?._id) {
|
|
69647
69804
|
role._id = getExternalRoleID(role._id, role.version);
|
|
69648
|
-
}
|
|
69649
|
-
|
|
69650
|
-
|
|
69651
|
-
|
|
69652
|
-
|
|
69653
|
-
|
|
69805
|
+
}
|
|
69806
|
+
return Object.keys(role).length === 0 ? void 0 : role;
|
|
69807
|
+
}
|
|
69808
|
+
async function getRole(roleId, opts) {
|
|
69809
|
+
const db = getAppDB();
|
|
69810
|
+
const roleList = [];
|
|
69811
|
+
if (!isBuiltin(roleId)) {
|
|
69812
|
+
const role = await db.tryGet(getDBRoleID(roleId));
|
|
69813
|
+
if (role) {
|
|
69814
|
+
roleList.push(role);
|
|
69654
69815
|
}
|
|
69655
69816
|
}
|
|
69656
|
-
return
|
|
69817
|
+
return findRole(roleId, roleList, opts);
|
|
69818
|
+
}
|
|
69819
|
+
async function saveRoles(roles) {
|
|
69820
|
+
const db = getAppDB();
|
|
69821
|
+
await db.bulkDocs(
|
|
69822
|
+
roles.filter((role) => role._id).map((role) => ({
|
|
69823
|
+
...role,
|
|
69824
|
+
_id: prefixRoleID(role._id)
|
|
69825
|
+
}))
|
|
69826
|
+
);
|
|
69657
69827
|
}
|
|
69658
69828
|
async function getAllUserRoles(userRoleId, opts) {
|
|
69829
|
+
const allRoles = await getAllRoles();
|
|
69659
69830
|
if (userRoleId === BUILTIN_IDS.ADMIN) {
|
|
69660
|
-
return
|
|
69831
|
+
return allRoles;
|
|
69661
69832
|
}
|
|
69662
|
-
|
|
69663
|
-
let roles =
|
|
69664
|
-
|
|
69665
|
-
|
|
69666
|
-
|
|
69667
|
-
currentRole = await getRole(currentRole.inherits);
|
|
69668
|
-
if (currentRole) {
|
|
69669
|
-
roles.push(currentRole);
|
|
69670
|
-
}
|
|
69833
|
+
const foundRole = findRole(userRoleId, allRoles, opts);
|
|
69834
|
+
let roles = [];
|
|
69835
|
+
if (foundRole) {
|
|
69836
|
+
const traversal = new RoleHierarchyTraversal(allRoles, opts);
|
|
69837
|
+
roles = traversal.walk(foundRole);
|
|
69671
69838
|
}
|
|
69672
69839
|
return roles;
|
|
69673
69840
|
}
|
|
@@ -69717,7 +69884,22 @@ async function getAllRoles(appId) {
|
|
|
69717
69884
|
);
|
|
69718
69885
|
}
|
|
69719
69886
|
const builtinRoles = getBuiltinRoles();
|
|
69720
|
-
|
|
69887
|
+
let externalBuiltinRoles = [];
|
|
69888
|
+
if (!db || await shouldIncludePowerRole(db)) {
|
|
69889
|
+
externalBuiltinRoles = [
|
|
69890
|
+
BUILTIN_IDS.ADMIN,
|
|
69891
|
+
BUILTIN_IDS.POWER,
|
|
69892
|
+
BUILTIN_IDS.BASIC,
|
|
69893
|
+
BUILTIN_IDS.PUBLIC
|
|
69894
|
+
];
|
|
69895
|
+
} else {
|
|
69896
|
+
externalBuiltinRoles = [
|
|
69897
|
+
BUILTIN_IDS.ADMIN,
|
|
69898
|
+
BUILTIN_IDS.BASIC,
|
|
69899
|
+
BUILTIN_IDS.PUBLIC
|
|
69900
|
+
];
|
|
69901
|
+
}
|
|
69902
|
+
for (let builtinRoleId of externalBuiltinRoles) {
|
|
69721
69903
|
const builtinRole = builtinRoles[builtinRoleId];
|
|
69722
69904
|
const dbBuiltin = roles.filter(
|
|
69723
69905
|
(dbRole) => getExternalRoleID(dbRole._id, dbRole.version) === builtinRoleId
|
|
@@ -69744,6 +69926,15 @@ async function getAllRoles(appId) {
|
|
|
69744
69926
|
return roles;
|
|
69745
69927
|
}
|
|
69746
69928
|
}
|
|
69929
|
+
async function shouldIncludePowerRole(db) {
|
|
69930
|
+
const app = await db.tryGet("app_metadata" /* APP_METADATA */);
|
|
69931
|
+
const creationVersion = app?.creationVersion;
|
|
69932
|
+
if (!creationVersion || !import_semver.default.valid(creationVersion)) {
|
|
69933
|
+
return true;
|
|
69934
|
+
}
|
|
69935
|
+
const isGreaterThan3x = import_semver.default.gte(creationVersion, "3.0.0");
|
|
69936
|
+
return !isGreaterThan3x;
|
|
69937
|
+
}
|
|
69747
69938
|
var AccessController = class {
|
|
69748
69939
|
constructor() {
|
|
69749
69940
|
this.userHierarchies = {};
|
|
@@ -69757,7 +69948,7 @@ var AccessController = class {
|
|
|
69757
69948
|
roleIds = await getUserRoleIdHierarchy(userRoleId);
|
|
69758
69949
|
this.userHierarchies[userRoleId] = roleIds;
|
|
69759
69950
|
}
|
|
69760
|
-
return roleIds?.
|
|
69951
|
+
return roleIds?.find((roleId) => compareRoleIds(roleId, tryingRoleId)) !== void 0;
|
|
69761
69952
|
}
|
|
69762
69953
|
async checkScreensAccess(screens, userRoleId) {
|
|
69763
69954
|
let accessibleScreens = [];
|
|
@@ -69784,13 +69975,22 @@ function getDBRoleID(roleName) {
|
|
|
69784
69975
|
return prefixRoleID(roleName);
|
|
69785
69976
|
}
|
|
69786
69977
|
function getExternalRoleID(roleId, version) {
|
|
69787
|
-
if (roleId.startsWith("role" /* ROLE */) && (isBuiltin(roleId) || version === RoleIDVersion.NAME)) {
|
|
69978
|
+
if (roleId.startsWith(`${"role" /* ROLE */}${SEPARATOR}`) && (isBuiltin(roleId) || version === RoleIDVersion.NAME)) {
|
|
69788
69979
|
const parts = roleId.split(SEPARATOR);
|
|
69789
69980
|
parts.shift();
|
|
69790
69981
|
return parts.join(SEPARATOR);
|
|
69791
69982
|
}
|
|
69792
69983
|
return roleId;
|
|
69793
69984
|
}
|
|
69985
|
+
function getExternalRoleIDs(roleIds, version) {
|
|
69986
|
+
if (!roleIds) {
|
|
69987
|
+
return roleIds;
|
|
69988
|
+
} else if (typeof roleIds === "string") {
|
|
69989
|
+
return getExternalRoleID(roleIds, version);
|
|
69990
|
+
} else {
|
|
69991
|
+
return roleIds.map((roleId) => getExternalRoleID(roleId, version));
|
|
69992
|
+
}
|
|
69993
|
+
}
|
|
69794
69994
|
|
|
69795
69995
|
// src/users/utils.ts
|
|
69796
69996
|
var isBuilder2 = sdk_exports.users.isBuilder;
|
|
@@ -70590,7 +70790,7 @@ __export(installation_exports, {
|
|
|
70590
70790
|
getInstall: () => getInstall,
|
|
70591
70791
|
getInstallFromDB: () => getInstallFromDB
|
|
70592
70792
|
});
|
|
70593
|
-
var
|
|
70793
|
+
var import_semver2 = __toESM(require("semver"));
|
|
70594
70794
|
var getInstall = async () => {
|
|
70595
70795
|
return withCache("installation" /* INSTALLATION */, 86400 /* ONE_DAY */, getInstallFromDB, {
|
|
70596
70796
|
useTenancy: false
|
|
@@ -70659,8 +70859,8 @@ var checkInstallVersion = async () => {
|
|
|
70659
70859
|
const newVersion = environment_default.VERSION;
|
|
70660
70860
|
try {
|
|
70661
70861
|
if (currentVersion !== newVersion) {
|
|
70662
|
-
const isUpgrade =
|
|
70663
|
-
const isDowngrade =
|
|
70862
|
+
const isUpgrade = import_semver2.default.gt(newVersion, currentVersion);
|
|
70863
|
+
const isDowngrade = import_semver2.default.lt(newVersion, currentVersion);
|
|
70664
70864
|
const success = await updateVersion(newVersion);
|
|
70665
70865
|
if (success) {
|
|
70666
70866
|
await doInIdentityContext(
|
|
@@ -74435,6 +74635,7 @@ function timeMinusOneMinute() {
|
|
|
74435
74635
|
function finalise(ctx, opts = {}) {
|
|
74436
74636
|
ctx.publicEndpoint = opts.publicEndpoint || false;
|
|
74437
74637
|
ctx.isAuthenticated = opts.authenticated || false;
|
|
74638
|
+
ctx.loginMethod = opts.loginMethod;
|
|
74438
74639
|
ctx.user = opts.user;
|
|
74439
74640
|
ctx.internal = opts.internal || false;
|
|
74440
74641
|
ctx.version = opts.version;
|
|
@@ -74492,7 +74693,7 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74492
74693
|
apiKey = ctx.request.headers["authorization" /* AUTHORIZATION */].split(" ")[1];
|
|
74493
74694
|
}
|
|
74494
74695
|
const tenantId = ctx.request.headers["x-budibase-tenant-id" /* TENANT_ID */];
|
|
74495
|
-
let authenticated = false, user =
|
|
74696
|
+
let authenticated = false, user = void 0, internal = false, loginMethod = void 0;
|
|
74496
74697
|
if (authCookie && !apiKey) {
|
|
74497
74698
|
const sessionId = authCookie.sessionId;
|
|
74498
74699
|
const userId = authCookie.userId;
|
|
@@ -74514,6 +74715,7 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74514
74715
|
});
|
|
74515
74716
|
}
|
|
74516
74717
|
user.csrfToken = session.csrfToken;
|
|
74718
|
+
loginMethod = "cookie" /* COOKIE */;
|
|
74517
74719
|
if (session?.lastAccessedAt < timeMinusOneMinute()) {
|
|
74518
74720
|
await updateSessionTTL(session);
|
|
74519
74721
|
}
|
|
@@ -74530,17 +74732,16 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74530
74732
|
apiKey,
|
|
74531
74733
|
populateUser
|
|
74532
74734
|
);
|
|
74533
|
-
if (valid
|
|
74735
|
+
if (valid) {
|
|
74534
74736
|
authenticated = true;
|
|
74737
|
+
loginMethod = "api_key" /* API_KEY */;
|
|
74535
74738
|
user = foundUser;
|
|
74536
|
-
|
|
74537
|
-
authenticated = true;
|
|
74538
|
-
internal = true;
|
|
74739
|
+
internal = !foundUser;
|
|
74539
74740
|
}
|
|
74540
74741
|
}
|
|
74541
74742
|
if (!user && tenantId) {
|
|
74542
74743
|
user = { tenantId };
|
|
74543
|
-
} else if (user) {
|
|
74744
|
+
} else if (user && "password" in user) {
|
|
74544
74745
|
delete user.password;
|
|
74545
74746
|
}
|
|
74546
74747
|
if (!authenticated) {
|
|
@@ -74557,7 +74758,14 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74557
74758
|
status: user.status
|
|
74558
74759
|
});
|
|
74559
74760
|
}
|
|
74560
|
-
finalise(ctx, {
|
|
74761
|
+
finalise(ctx, {
|
|
74762
|
+
authenticated,
|
|
74763
|
+
user,
|
|
74764
|
+
internal,
|
|
74765
|
+
version,
|
|
74766
|
+
publicEndpoint,
|
|
74767
|
+
loginMethod
|
|
74768
|
+
});
|
|
74561
74769
|
if (isUser(user)) {
|
|
74562
74770
|
return doInUserContext(user, ctx, next);
|
|
74563
74771
|
} else {
|
|
@@ -75294,7 +75502,7 @@ var import_knex2 = require("knex");
|
|
|
75294
75502
|
// src/sql/sqlTable.ts
|
|
75295
75503
|
var import_knex = require("knex");
|
|
75296
75504
|
function isIgnoredType(type) {
|
|
75297
|
-
const ignored = ["link" /* LINK */, "formula" /* FORMULA */];
|
|
75505
|
+
const ignored = ["link" /* LINK */, "formula" /* FORMULA */, "ai" /* AI */];
|
|
75298
75506
|
return ignored.indexOf(type) !== -1;
|
|
75299
75507
|
}
|
|
75300
75508
|
function generateSchema(schema, table, tables, oldTable = null, renamed) {
|
|
@@ -75390,6 +75598,8 @@ function generateSchema(schema, table, tables, oldTable = null, renamed) {
|
|
|
75390
75598
|
break;
|
|
75391
75599
|
case "formula" /* FORMULA */:
|
|
75392
75600
|
break;
|
|
75601
|
+
case "ai" /* AI */:
|
|
75602
|
+
break;
|
|
75393
75603
|
case "attachment" /* ATTACHMENTS */:
|
|
75394
75604
|
case "attachment_single" /* ATTACHMENT_SINGLE */:
|
|
75395
75605
|
case "signature_single" /* SIGNATURE_SINGLE */:
|
|
@@ -75521,7 +75731,7 @@ var SqlTableQueryBuilder = class {
|
|
|
75521
75731
|
var sqlTable_default = SqlTableQueryBuilder;
|
|
75522
75732
|
|
|
75523
75733
|
// src/sql/sql.ts
|
|
75524
|
-
var
|
|
75734
|
+
var import_lodash5 = require("lodash");
|
|
75525
75735
|
var COUNT_FIELD_NAME = "__bb_total";
|
|
75526
75736
|
function getBaseLimit() {
|
|
75527
75737
|
const envLimit = environment_default.SQL_MAX_ROWS ? parseInt(environment_default.SQL_MAX_ROWS) : null;
|
|
@@ -75562,6 +75772,35 @@ function convertBooleans(query) {
|
|
|
75562
75772
|
function isSqs(table) {
|
|
75563
75773
|
return table.sourceType === "internal" /* INTERNAL */ || table.sourceId === INTERNAL_TABLE_SOURCE_ID;
|
|
75564
75774
|
}
|
|
75775
|
+
function escapeQuotes(value, quoteChar = '"') {
|
|
75776
|
+
return value.replace(new RegExp(quoteChar, "g"), `${quoteChar}${quoteChar}`);
|
|
75777
|
+
}
|
|
75778
|
+
function wrap(value, quoteChar = '"') {
|
|
75779
|
+
return `${quoteChar}${escapeQuotes(value, quoteChar)}${quoteChar}`;
|
|
75780
|
+
}
|
|
75781
|
+
function stringifyArray(value, quoteStyle = '"') {
|
|
75782
|
+
for (let i in value) {
|
|
75783
|
+
if (typeof value[i] === "string") {
|
|
75784
|
+
value[i] = wrap(value[i], quoteStyle);
|
|
75785
|
+
}
|
|
75786
|
+
}
|
|
75787
|
+
return `[${value.join(",")}]`;
|
|
75788
|
+
}
|
|
75789
|
+
var allowEmptyRelationships = {
|
|
75790
|
+
["equal" /* EQUAL */]: false,
|
|
75791
|
+
["notEqual" /* NOT_EQUAL */]: true,
|
|
75792
|
+
["empty" /* EMPTY */]: false,
|
|
75793
|
+
["notEmpty" /* NOT_EMPTY */]: true,
|
|
75794
|
+
["fuzzy" /* FUZZY */]: false,
|
|
75795
|
+
["string" /* STRING */]: false,
|
|
75796
|
+
["range" /* RANGE */]: false,
|
|
75797
|
+
["contains" /* CONTAINS */]: false,
|
|
75798
|
+
["notContains" /* NOT_CONTAINS */]: true,
|
|
75799
|
+
["containsAny" /* CONTAINS_ANY */]: false,
|
|
75800
|
+
["oneOf" /* ONE_OF */]: false,
|
|
75801
|
+
["$and" /* AND */]: false,
|
|
75802
|
+
["$or" /* OR */]: false
|
|
75803
|
+
};
|
|
75565
75804
|
var InternalBuilder = class {
|
|
75566
75805
|
constructor(client, knex3, query) {
|
|
75567
75806
|
// states the various situations in which we need a full mapped select statement
|
|
@@ -75584,28 +75823,24 @@ var InternalBuilder = class {
|
|
|
75584
75823
|
get table() {
|
|
75585
75824
|
return this.query.meta.table;
|
|
75586
75825
|
}
|
|
75826
|
+
get knexClient() {
|
|
75827
|
+
return this.knex.client;
|
|
75828
|
+
}
|
|
75587
75829
|
getFieldSchema(key) {
|
|
75588
75830
|
const { column } = this.splitter.run(key);
|
|
75589
75831
|
return this.table.schema[column];
|
|
75590
75832
|
}
|
|
75833
|
+
supportsILike() {
|
|
75834
|
+
return !(this.client === "oracledb" /* ORACLE */ || this.client === "sqlite3" /* SQL_LITE */);
|
|
75835
|
+
}
|
|
75591
75836
|
quoteChars() {
|
|
75592
|
-
|
|
75593
|
-
|
|
75594
|
-
case "pg" /* POSTGRES */:
|
|
75595
|
-
return ['"', '"'];
|
|
75596
|
-
case "mssql" /* MS_SQL */:
|
|
75597
|
-
return ["[", "]"];
|
|
75598
|
-
case "mariadb" /* MARIADB */:
|
|
75599
|
-
case "mysql2" /* MY_SQL */:
|
|
75600
|
-
case "sqlite3" /* SQL_LITE */:
|
|
75601
|
-
return ["`", "`"];
|
|
75602
|
-
}
|
|
75837
|
+
const wrapped = this.knexClient.wrapIdentifier("foo", {});
|
|
75838
|
+
return [wrapped[0], wrapped[wrapped.length - 1]];
|
|
75603
75839
|
}
|
|
75604
|
-
// Takes a string like foo and returns a quoted string like [foo] for SQL
|
|
75605
|
-
// and "foo" for Postgres.
|
|
75840
|
+
// Takes a string like foo and returns a quoted string like [foo] for SQL
|
|
75841
|
+
// Server and "foo" for Postgres.
|
|
75606
75842
|
quote(str) {
|
|
75607
|
-
|
|
75608
|
-
return `${start2}${str}${end2}`;
|
|
75843
|
+
return this.knexClient.wrapIdentifier(str, {});
|
|
75609
75844
|
}
|
|
75610
75845
|
isQuoted(key) {
|
|
75611
75846
|
const [start2, end2] = this.quoteChars();
|
|
@@ -75620,6 +75855,27 @@ var InternalBuilder = class {
|
|
|
75620
75855
|
}
|
|
75621
75856
|
return key.map((part) => this.quote(part)).join(".");
|
|
75622
75857
|
}
|
|
75858
|
+
quotedValue(value) {
|
|
75859
|
+
const formatter = this.knexClient.formatter(this.knexClient.queryBuilder());
|
|
75860
|
+
return formatter.wrap(value, false);
|
|
75861
|
+
}
|
|
75862
|
+
rawQuotedValue(value) {
|
|
75863
|
+
return this.knex.raw(this.quotedValue(value));
|
|
75864
|
+
}
|
|
75865
|
+
// Unfortuantely we cannot rely on knex's identifier escaping because it trims
|
|
75866
|
+
// the identifier string before escaping it, which breaks cases for us where
|
|
75867
|
+
// columns that start or end with a space aren't referenced correctly anymore.
|
|
75868
|
+
//
|
|
75869
|
+
// So whenever you're using an identifier binding in knex, e.g. knex.raw("??
|
|
75870
|
+
// as ?", ["foo", "bar"]), you need to make sure you call this:
|
|
75871
|
+
//
|
|
75872
|
+
// knex.raw("?? as ?", [this.quotedIdentifier("foo"), "bar"])
|
|
75873
|
+
//
|
|
75874
|
+
// Issue we filed against knex about this:
|
|
75875
|
+
// https://github.com/knex/knex/issues/6143
|
|
75876
|
+
rawQuotedIdentifier(key) {
|
|
75877
|
+
return this.knex.raw(this.quotedIdentifier(key));
|
|
75878
|
+
}
|
|
75623
75879
|
// Turns an identifier like a.b.c or `a`.`b`.`c` into ["a", "b", "c"]
|
|
75624
75880
|
splitIdentifier(key) {
|
|
75625
75881
|
const [start2, end2] = this.quoteChars();
|
|
@@ -75658,7 +75914,7 @@ var InternalBuilder = class {
|
|
|
75658
75914
|
const alias = this.getTableName(endpoint.entityId);
|
|
75659
75915
|
const schema = meta.table.schema;
|
|
75660
75916
|
if (!this.isFullSelectStatementRequired()) {
|
|
75661
|
-
return [this.knex.raw(`${
|
|
75917
|
+
return [this.knex.raw("??", [`${alias}.*`])];
|
|
75662
75918
|
}
|
|
75663
75919
|
return resource.fields.map((field) => {
|
|
75664
75920
|
const parts = field.split(/\./g);
|
|
@@ -75672,17 +75928,21 @@ var InternalBuilder = class {
|
|
|
75672
75928
|
}).filter(({ table }) => !table || table === alias).map(({ table, column, field }) => {
|
|
75673
75929
|
const columnSchema = schema[column];
|
|
75674
75930
|
if (this.SPECIAL_SELECT_CASES.POSTGRES_MONEY(columnSchema)) {
|
|
75675
|
-
return this.knex.raw(
|
|
75676
|
-
|
|
75677
|
-
|
|
75678
|
-
|
|
75679
|
-
);
|
|
75931
|
+
return this.knex.raw(`??::money::numeric as "${field}"`, [
|
|
75932
|
+
this.rawQuotedIdentifier([table, column].join(".")),
|
|
75933
|
+
field
|
|
75934
|
+
]);
|
|
75680
75935
|
}
|
|
75681
75936
|
if (this.SPECIAL_SELECT_CASES.MSSQL_DATES(columnSchema)) {
|
|
75682
|
-
return this.knex.raw(`CONVERT(varchar,
|
|
75937
|
+
return this.knex.raw(`CONVERT(varchar, ??, 108) as "${field}"`, [
|
|
75938
|
+
this.rawQuotedIdentifier(field)
|
|
75939
|
+
]);
|
|
75940
|
+
}
|
|
75941
|
+
if (table) {
|
|
75942
|
+
return this.rawQuotedIdentifier(`${table}.${column}`);
|
|
75943
|
+
} else {
|
|
75944
|
+
return this.rawQuotedIdentifier(field);
|
|
75683
75945
|
}
|
|
75684
|
-
const quoted = table ? `${this.quote(table)}.${this.quote(column)}` : this.quote(field);
|
|
75685
|
-
return this.knex.raw(quoted);
|
|
75686
75946
|
});
|
|
75687
75947
|
}
|
|
75688
75948
|
// OracleDB can't use character-large-objects (CLOBs) in WHERE clauses,
|
|
@@ -75697,12 +75957,15 @@ var InternalBuilder = class {
|
|
|
75697
75957
|
const parts = this.splitIdentifier(field);
|
|
75698
75958
|
const col = parts.pop();
|
|
75699
75959
|
const schema = this.table.schema[col];
|
|
75700
|
-
let identifier = this.
|
|
75960
|
+
let identifier = this.rawQuotedIdentifier(field);
|
|
75701
75961
|
if (schema.type === "string" /* STRING */ || schema.type === "longform" /* LONGFORM */ || schema.type === "bb_reference_single" /* BB_REFERENCE_SINGLE */ || schema.type === "bb_reference" /* BB_REFERENCE */ || schema.type === "options" /* OPTIONS */ || schema.type === "barcodeqr" /* BARCODEQR */) {
|
|
75702
75962
|
if (opts?.forSelect) {
|
|
75703
|
-
identifier =
|
|
75963
|
+
identifier = this.knex.raw("to_char(??) as ??", [
|
|
75964
|
+
identifier,
|
|
75965
|
+
this.rawQuotedIdentifier(col)
|
|
75966
|
+
]);
|
|
75704
75967
|
} else {
|
|
75705
|
-
identifier =
|
|
75968
|
+
identifier = this.knex.raw("to_char(??)", [identifier]);
|
|
75706
75969
|
}
|
|
75707
75970
|
}
|
|
75708
75971
|
return identifier;
|
|
@@ -75747,7 +76010,7 @@ var InternalBuilder = class {
|
|
|
75747
76010
|
return body2;
|
|
75748
76011
|
}
|
|
75749
76012
|
parseFilters(filters) {
|
|
75750
|
-
filters = (0,
|
|
76013
|
+
filters = (0, import_lodash5.cloneDeep)(filters);
|
|
75751
76014
|
for (const op of Object.values(BasicOperator)) {
|
|
75752
76015
|
const filter = filters[op];
|
|
75753
76016
|
if (!filter) {
|
|
@@ -75806,21 +76069,32 @@ var InternalBuilder = class {
|
|
|
75806
76069
|
const document = relationship.from?.split(".")[0] || "";
|
|
75807
76070
|
return query.andWhere(`${document}.fieldName`, "=", relationship.column);
|
|
75808
76071
|
}
|
|
75809
|
-
addRelationshipForFilter(query, filterKey, whereCb) {
|
|
75810
|
-
const mainKnex = this.knex;
|
|
76072
|
+
addRelationshipForFilter(query, allowEmptyRelationships2, filterKey, whereCb) {
|
|
75811
76073
|
const { relationships, endpoint, tableAliases: aliases } = this.query;
|
|
75812
76074
|
const tableName = endpoint.entityId;
|
|
75813
76075
|
const fromAlias = aliases?.[tableName] || tableName;
|
|
75814
|
-
const matches2 = (
|
|
76076
|
+
const matches2 = (value) => filterKey.match(new RegExp(`^${value}\\.`));
|
|
75815
76077
|
if (!relationships) {
|
|
75816
76078
|
return query;
|
|
75817
76079
|
}
|
|
75818
76080
|
for (const relationship of relationships) {
|
|
75819
76081
|
const relatedTableName = relationship.tableName;
|
|
75820
76082
|
const toAlias = aliases?.[relatedTableName] || relatedTableName;
|
|
75821
|
-
|
|
75822
|
-
|
|
76083
|
+
const matchesTableName = matches2(relatedTableName) || matches2(toAlias);
|
|
76084
|
+
const matchesRelationName = matches2(relationship.column);
|
|
76085
|
+
if ((matchesTableName || matchesRelationName) && relationship.to && relationship.tableName) {
|
|
76086
|
+
const joinTable = this.knex.select(this.knex.raw(1)).from({ [toAlias]: relatedTableName });
|
|
76087
|
+
let subQuery = joinTable.clone();
|
|
75823
76088
|
const manyToMany = validateManyToMany(relationship);
|
|
76089
|
+
let updatedKey;
|
|
76090
|
+
if (!matchesTableName) {
|
|
76091
|
+
updatedKey = filterKey.replace(
|
|
76092
|
+
new RegExp(`^${relationship.column}.`),
|
|
76093
|
+
`${aliases[relationship.tableName]}.`
|
|
76094
|
+
);
|
|
76095
|
+
} else {
|
|
76096
|
+
updatedKey = filterKey;
|
|
76097
|
+
}
|
|
75824
76098
|
if (manyToMany) {
|
|
75825
76099
|
const throughAlias = aliases?.[manyToMany.through] || relationship.through;
|
|
75826
76100
|
let throughTable = this.tableNameWithSchema(manyToMany.through, {
|
|
@@ -75836,24 +76110,40 @@ var InternalBuilder = class {
|
|
|
75836
76110
|
}).where(
|
|
75837
76111
|
`${throughAlias}.${manyToMany.from}`,
|
|
75838
76112
|
"=",
|
|
75839
|
-
|
|
75840
|
-
this.quotedIdentifier(`${fromAlias}.${manyToMany.fromPrimary}`)
|
|
75841
|
-
)
|
|
76113
|
+
this.rawQuotedIdentifier(`${fromAlias}.${manyToMany.fromPrimary}`)
|
|
75842
76114
|
);
|
|
75843
76115
|
if (this.client === "sqlite3" /* SQL_LITE */) {
|
|
75844
76116
|
subQuery = this.addJoinFieldCheck(subQuery, manyToMany);
|
|
75845
76117
|
}
|
|
76118
|
+
query = query.where((q2) => {
|
|
76119
|
+
q2.whereExists(whereCb(updatedKey, subQuery));
|
|
76120
|
+
if (allowEmptyRelationships2) {
|
|
76121
|
+
q2.orWhereNotExists(
|
|
76122
|
+
joinTable.clone().innerJoin(throughTable, function() {
|
|
76123
|
+
this.on(
|
|
76124
|
+
`${fromAlias}.${manyToMany.fromPrimary}`,
|
|
76125
|
+
"=",
|
|
76126
|
+
`${throughAlias}.${manyToMany.from}`
|
|
76127
|
+
);
|
|
76128
|
+
})
|
|
76129
|
+
);
|
|
76130
|
+
}
|
|
76131
|
+
});
|
|
75846
76132
|
} else {
|
|
76133
|
+
const toKey = `${toAlias}.${relationship.to}`;
|
|
76134
|
+
const foreignKey = `${fromAlias}.${relationship.from}`;
|
|
75847
76135
|
subQuery = subQuery.where(
|
|
75848
|
-
|
|
76136
|
+
toKey,
|
|
75849
76137
|
"=",
|
|
75850
|
-
|
|
75851
|
-
this.quotedIdentifier(`${fromAlias}.${relationship.from}`)
|
|
75852
|
-
)
|
|
76138
|
+
this.rawQuotedIdentifier(foreignKey)
|
|
75853
76139
|
);
|
|
76140
|
+
query = query.where((q2) => {
|
|
76141
|
+
q2.whereExists(whereCb(updatedKey, subQuery.clone()));
|
|
76142
|
+
if (allowEmptyRelationships2) {
|
|
76143
|
+
q2.orWhereNotExists(subQuery);
|
|
76144
|
+
}
|
|
76145
|
+
});
|
|
75854
76146
|
}
|
|
75855
|
-
query = query.whereExists(whereCb(subQuery));
|
|
75856
|
-
break;
|
|
75857
76147
|
}
|
|
75858
76148
|
}
|
|
75859
76149
|
return query;
|
|
@@ -75866,14 +76156,14 @@ var InternalBuilder = class {
|
|
|
75866
76156
|
const builder = this;
|
|
75867
76157
|
filters = this.parseFilters({ ...filters });
|
|
75868
76158
|
const aliases = this.query.tableAliases;
|
|
75869
|
-
const
|
|
76159
|
+
const shouldOr = filters.allOr;
|
|
75870
76160
|
const isSqlite = this.client === "sqlite3" /* SQL_LITE */;
|
|
75871
76161
|
const tableName = isSqlite ? this.table._id : this.table.name;
|
|
75872
76162
|
function getTableAlias(name) {
|
|
75873
76163
|
const alias = aliases?.[name];
|
|
75874
76164
|
return alias || name;
|
|
75875
76165
|
}
|
|
75876
|
-
function iterate(structure, fn, complexKeyFn) {
|
|
76166
|
+
function iterate(structure, operation, fn, complexKeyFn) {
|
|
75877
76167
|
const handleRelationship = (q2, key, value) => {
|
|
75878
76168
|
const [filterTableName, ...otherProperties] = key.split(".");
|
|
75879
76169
|
const property = otherProperties.join(".");
|
|
@@ -75905,85 +76195,104 @@ var InternalBuilder = class {
|
|
|
75905
76195
|
value
|
|
75906
76196
|
);
|
|
75907
76197
|
} else if (shouldProcessRelationship) {
|
|
75908
|
-
if (
|
|
76198
|
+
if (shouldOr) {
|
|
75909
76199
|
query = query.or;
|
|
75910
76200
|
}
|
|
75911
|
-
query = builder.addRelationshipForFilter(
|
|
75912
|
-
|
|
75913
|
-
|
|
76201
|
+
query = builder.addRelationshipForFilter(
|
|
76202
|
+
query,
|
|
76203
|
+
allowEmptyRelationships[operation],
|
|
76204
|
+
updatedKey,
|
|
76205
|
+
(updatedKey2, q2) => {
|
|
76206
|
+
return handleRelationship(q2, updatedKey2, value);
|
|
76207
|
+
}
|
|
76208
|
+
);
|
|
75914
76209
|
}
|
|
75915
76210
|
}
|
|
75916
76211
|
}
|
|
75917
76212
|
const like = (q2, key, value) => {
|
|
75918
|
-
|
|
75919
|
-
|
|
75920
|
-
|
|
75921
|
-
|
|
75922
|
-
|
|
75923
|
-
|
|
75924
|
-
return q2[rawFnc](`LOWER(${this.quotedIdentifier(key)}) LIKE ?`, [
|
|
76213
|
+
if (filters?.fuzzyOr || shouldOr) {
|
|
76214
|
+
q2 = q2.or;
|
|
76215
|
+
}
|
|
76216
|
+
if (this.client === "oracledb" /* ORACLE */ || this.client === "sqlite3" /* SQL_LITE */) {
|
|
76217
|
+
return q2.whereRaw(`LOWER(??) LIKE ?`, [
|
|
76218
|
+
this.rawQuotedIdentifier(key),
|
|
75925
76219
|
`%${value.toLowerCase()}%`
|
|
75926
76220
|
]);
|
|
75927
76221
|
}
|
|
76222
|
+
return q2.whereILike(
|
|
76223
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76224
|
+
this.rawQuotedIdentifier(key),
|
|
76225
|
+
this.knex.raw("?", [`%${value}%`])
|
|
76226
|
+
);
|
|
75928
76227
|
};
|
|
75929
76228
|
const contains = (mode, any = false) => {
|
|
75930
|
-
|
|
75931
|
-
|
|
75932
|
-
|
|
75933
|
-
|
|
75934
|
-
|
|
75935
|
-
|
|
75936
|
-
}
|
|
76229
|
+
function addModifiers(q2) {
|
|
76230
|
+
if (shouldOr || mode === filters?.containsAny) {
|
|
76231
|
+
q2 = q2.or;
|
|
76232
|
+
}
|
|
76233
|
+
if (mode === filters?.notContains) {
|
|
76234
|
+
q2 = q2.not;
|
|
75937
76235
|
}
|
|
75938
|
-
return
|
|
76236
|
+
return q2;
|
|
75939
76237
|
}
|
|
75940
76238
|
if (this.client === "pg" /* POSTGRES */) {
|
|
75941
|
-
iterate(mode, (q2, key, value) => {
|
|
75942
|
-
|
|
75943
|
-
|
|
75944
|
-
|
|
75945
|
-
|
|
75946
|
-
|
|
75947
|
-
|
|
75948
|
-
|
|
75949
|
-
|
|
75950
|
-
|
|
75951
|
-
|
|
75952
|
-
|
|
76239
|
+
iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
|
|
76240
|
+
q2 = addModifiers(q2);
|
|
76241
|
+
if (any) {
|
|
76242
|
+
return q2.whereRaw(`COALESCE(??::jsonb \\?| array??, FALSE)`, [
|
|
76243
|
+
this.rawQuotedIdentifier(key),
|
|
76244
|
+
this.knex.raw(stringifyArray(value, "'"))
|
|
76245
|
+
]);
|
|
76246
|
+
} else {
|
|
76247
|
+
return q2.whereRaw(`COALESCE(??::jsonb @> '??', FALSE)`, [
|
|
76248
|
+
this.rawQuotedIdentifier(key),
|
|
76249
|
+
this.knex.raw(stringifyArray(value))
|
|
76250
|
+
]);
|
|
76251
|
+
}
|
|
75953
76252
|
});
|
|
75954
76253
|
} else if (this.client === "mysql2" /* MY_SQL */ || this.client === "mariadb" /* MARIADB */) {
|
|
75955
|
-
|
|
75956
|
-
|
|
75957
|
-
|
|
75958
|
-
|
|
75959
|
-
|
|
75960
|
-
|
|
75961
|
-
);
|
|
76254
|
+
iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
|
|
76255
|
+
return addModifiers(q2).whereRaw(`COALESCE(?(??, ?), FALSE)`, [
|
|
76256
|
+
this.knex.raw(any ? "JSON_OVERLAPS" : "JSON_CONTAINS"),
|
|
76257
|
+
this.rawQuotedIdentifier(key),
|
|
76258
|
+
this.knex.raw(wrap(stringifyArray(value)))
|
|
76259
|
+
]);
|
|
75962
76260
|
});
|
|
75963
76261
|
} else {
|
|
75964
|
-
|
|
75965
|
-
|
|
75966
|
-
let statement = "";
|
|
75967
|
-
const identifier = this.quotedIdentifier(key);
|
|
75968
|
-
for (let i in value) {
|
|
75969
|
-
if (typeof value[i] === "string") {
|
|
75970
|
-
value[i] = `%"${value[i].toLowerCase()}"%`;
|
|
75971
|
-
} else {
|
|
75972
|
-
value[i] = `%${value[i]}%`;
|
|
75973
|
-
}
|
|
75974
|
-
statement += `${statement ? andOr : ""}COALESCE(LOWER(${identifier}), '') LIKE ?`;
|
|
75975
|
-
}
|
|
75976
|
-
if (statement === "") {
|
|
76262
|
+
iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
|
|
76263
|
+
if (value.length === 0) {
|
|
75977
76264
|
return q2;
|
|
75978
76265
|
}
|
|
75979
|
-
|
|
75980
|
-
|
|
75981
|
-
|
|
75982
|
-
|
|
75983
|
-
)
|
|
75984
|
-
|
|
75985
|
-
|
|
75986
|
-
|
|
76266
|
+
q2 = q2.where((subQuery) => {
|
|
76267
|
+
if (mode === filters?.notContains) {
|
|
76268
|
+
subQuery = subQuery.not;
|
|
76269
|
+
}
|
|
76270
|
+
subQuery = subQuery.where((subSubQuery) => {
|
|
76271
|
+
for (const elem of value) {
|
|
76272
|
+
if (mode === filters?.containsAny) {
|
|
76273
|
+
subSubQuery = subSubQuery.or;
|
|
76274
|
+
} else {
|
|
76275
|
+
subSubQuery = subSubQuery.and;
|
|
76276
|
+
}
|
|
76277
|
+
const lower = typeof elem === "string" ? `"${elem.toLowerCase()}"` : elem;
|
|
76278
|
+
subSubQuery = subSubQuery.whereLike(
|
|
76279
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76280
|
+
this.knex.raw(`COALESCE(LOWER(??), '')`, [
|
|
76281
|
+
this.rawQuotedIdentifier(key)
|
|
76282
|
+
]),
|
|
76283
|
+
`%${lower}%`
|
|
76284
|
+
);
|
|
76285
|
+
}
|
|
76286
|
+
});
|
|
76287
|
+
if (mode === filters?.notContains) {
|
|
76288
|
+
subQuery = subQuery.or.whereNull(
|
|
76289
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76290
|
+
this.rawQuotedIdentifier(key)
|
|
76291
|
+
);
|
|
76292
|
+
}
|
|
76293
|
+
return subQuery;
|
|
76294
|
+
});
|
|
76295
|
+
return q2;
|
|
75987
76296
|
});
|
|
75988
76297
|
}
|
|
75989
76298
|
};
|
|
@@ -76006,48 +76315,49 @@ var InternalBuilder = class {
|
|
|
76006
76315
|
});
|
|
76007
76316
|
}
|
|
76008
76317
|
if (filters.oneOf) {
|
|
76009
|
-
const fnc = allOr ? "orWhereIn" : "whereIn";
|
|
76010
76318
|
iterate(
|
|
76011
76319
|
filters.oneOf,
|
|
76320
|
+
"oneOf" /* ONE_OF */,
|
|
76012
76321
|
(q2, key, array) => {
|
|
76322
|
+
if (shouldOr) {
|
|
76323
|
+
q2 = q2.or;
|
|
76324
|
+
}
|
|
76013
76325
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76014
76326
|
key = this.convertClobs(key);
|
|
76015
|
-
array = Array.isArray(array) ? array : [array];
|
|
76016
|
-
const binding = new Array(array.length).fill("?").join(",");
|
|
76017
|
-
return q2.whereRaw(`${key} IN (${binding})`, array);
|
|
76018
|
-
} else {
|
|
76019
|
-
return q2[fnc](key, Array.isArray(array) ? array : [array]);
|
|
76020
76327
|
}
|
|
76328
|
+
return q2.whereIn(key, Array.isArray(array) ? array : [array]);
|
|
76021
76329
|
},
|
|
76022
76330
|
(q2, key, array) => {
|
|
76331
|
+
if (shouldOr) {
|
|
76332
|
+
q2 = q2.or;
|
|
76333
|
+
}
|
|
76023
76334
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76024
|
-
|
|
76025
|
-
const binding = `(${array.map((a) => `(${new Array(a.length).fill("?").join(",")})`).join(",")})`;
|
|
76026
|
-
return q2.whereRaw(`${keyStr} IN ${binding}`, array.flat());
|
|
76027
|
-
} else {
|
|
76028
|
-
return q2[fnc](key, Array.isArray(array) ? array : [array]);
|
|
76335
|
+
key = key.map((k) => this.convertClobs(k));
|
|
76029
76336
|
}
|
|
76337
|
+
return q2.whereIn(key, Array.isArray(array) ? array : [array]);
|
|
76030
76338
|
}
|
|
76031
76339
|
);
|
|
76032
76340
|
}
|
|
76033
76341
|
if (filters.string) {
|
|
76034
|
-
iterate(filters.string, (q2, key, value) => {
|
|
76035
|
-
|
|
76036
|
-
|
|
76037
|
-
|
|
76038
|
-
|
|
76039
|
-
|
|
76040
|
-
|
|
76342
|
+
iterate(filters.string, "string" /* STRING */, (q2, key, value) => {
|
|
76343
|
+
if (shouldOr) {
|
|
76344
|
+
q2 = q2.or;
|
|
76345
|
+
}
|
|
76346
|
+
if (this.client === "oracledb" /* ORACLE */ || this.client === "sqlite3" /* SQL_LITE */) {
|
|
76347
|
+
return q2.whereRaw(`LOWER(??) LIKE ?`, [
|
|
76348
|
+
this.rawQuotedIdentifier(key),
|
|
76041
76349
|
`${value.toLowerCase()}%`
|
|
76042
76350
|
]);
|
|
76351
|
+
} else {
|
|
76352
|
+
return q2.whereILike(key, `${value}%`);
|
|
76043
76353
|
}
|
|
76044
76354
|
});
|
|
76045
76355
|
}
|
|
76046
76356
|
if (filters.fuzzy) {
|
|
76047
|
-
iterate(filters.fuzzy, like);
|
|
76357
|
+
iterate(filters.fuzzy, "fuzzy" /* FUZZY */, like);
|
|
76048
76358
|
}
|
|
76049
76359
|
if (filters.range) {
|
|
76050
|
-
iterate(filters.range, (q2, key, value) => {
|
|
76360
|
+
iterate(filters.range, "range" /* RANGE */, (q2, key, value) => {
|
|
76051
76361
|
const isEmptyObject = (val) => {
|
|
76052
76362
|
return val && Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;
|
|
76053
76363
|
};
|
|
@@ -76059,92 +76369,94 @@ var InternalBuilder = class {
|
|
|
76059
76369
|
}
|
|
76060
76370
|
const lowValid = isValidFilter(value.low), highValid = isValidFilter(value.high);
|
|
76061
76371
|
const schema = this.getFieldSchema(key);
|
|
76372
|
+
let rawKey = key;
|
|
76373
|
+
let high = value.high;
|
|
76374
|
+
let low = value.low;
|
|
76062
76375
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76063
|
-
|
|
76376
|
+
rawKey = this.convertClobs(key);
|
|
76377
|
+
} else if (this.client === "sqlite3" /* SQL_LITE */ && schema?.type === "bigint" /* BIGINT */) {
|
|
76378
|
+
rawKey = this.knex.raw("CAST(?? AS INTEGER)", [
|
|
76379
|
+
this.rawQuotedIdentifier(key)
|
|
76380
|
+
]);
|
|
76381
|
+
high = this.knex.raw("CAST(? AS INTEGER)", [value.high]);
|
|
76382
|
+
low = this.knex.raw("CAST(? AS INTEGER)", [value.low]);
|
|
76383
|
+
}
|
|
76384
|
+
if (shouldOr) {
|
|
76385
|
+
q2 = q2.or;
|
|
76064
76386
|
}
|
|
76065
76387
|
if (lowValid && highValid) {
|
|
76066
|
-
|
|
76067
|
-
return q2.whereRaw(
|
|
76068
|
-
`CAST(${key} AS INTEGER) BETWEEN CAST(? AS INTEGER) AND CAST(? AS INTEGER)`,
|
|
76069
|
-
[value.low, value.high]
|
|
76070
|
-
);
|
|
76071
|
-
} else {
|
|
76072
|
-
const fnc = allOr ? "orWhereBetween" : "whereBetween";
|
|
76073
|
-
return q2[fnc](key, [value.low, value.high]);
|
|
76074
|
-
}
|
|
76388
|
+
return q2.whereBetween(rawKey, [low, high]);
|
|
76075
76389
|
} else if (lowValid) {
|
|
76076
|
-
|
|
76077
|
-
return q2.whereRaw(`CAST(${key} AS INTEGER) >= CAST(? AS INTEGER)`, [
|
|
76078
|
-
value.low
|
|
76079
|
-
]);
|
|
76080
|
-
} else {
|
|
76081
|
-
const fnc = allOr ? "orWhere" : "where";
|
|
76082
|
-
return q2[fnc](key, ">=", value.low);
|
|
76083
|
-
}
|
|
76390
|
+
return q2.where(rawKey, ">=", low);
|
|
76084
76391
|
} else if (highValid) {
|
|
76085
|
-
|
|
76086
|
-
return q2.whereRaw(`CAST(${key} AS INTEGER) <= CAST(? AS INTEGER)`, [
|
|
76087
|
-
value.high
|
|
76088
|
-
]);
|
|
76089
|
-
} else {
|
|
76090
|
-
const fnc = allOr ? "orWhere" : "where";
|
|
76091
|
-
return q2[fnc](key, "<=", value.high);
|
|
76092
|
-
}
|
|
76392
|
+
return q2.where(rawKey, "<=", high);
|
|
76093
76393
|
}
|
|
76094
76394
|
return q2;
|
|
76095
76395
|
});
|
|
76096
76396
|
}
|
|
76097
76397
|
if (filters.equal) {
|
|
76098
|
-
iterate(filters.equal, (q2, key, value) => {
|
|
76099
|
-
|
|
76398
|
+
iterate(filters.equal, "equal" /* EQUAL */, (q2, key, value) => {
|
|
76399
|
+
if (shouldOr) {
|
|
76400
|
+
q2 = q2.or;
|
|
76401
|
+
}
|
|
76100
76402
|
if (this.client === "mssql" /* MS_SQL */) {
|
|
76101
|
-
return q2[
|
|
76102
|
-
|
|
76103
|
-
[value]
|
|
76104
|
-
);
|
|
76105
|
-
} else if (this.client === "oracledb" /* ORACLE */) {
|
|
76106
|
-
const identifier = this.convertClobs(key);
|
|
76107
|
-
return q2[fnc](`(${identifier} IS NOT NULL AND ${identifier} = ?)`, [
|
|
76403
|
+
return q2.whereRaw(`CASE WHEN ?? = ? THEN 1 ELSE 0 END = 1`, [
|
|
76404
|
+
this.rawQuotedIdentifier(key),
|
|
76108
76405
|
value
|
|
76109
76406
|
]);
|
|
76407
|
+
} else if (this.client === "oracledb" /* ORACLE */) {
|
|
76408
|
+
const identifier = this.convertClobs(key);
|
|
76409
|
+
return q2.where(
|
|
76410
|
+
(subq) => (
|
|
76411
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76412
|
+
subq.whereNotNull(identifier).andWhere(identifier, value)
|
|
76413
|
+
)
|
|
76414
|
+
);
|
|
76110
76415
|
} else {
|
|
76111
|
-
return q2
|
|
76416
|
+
return q2.whereRaw(`COALESCE(?? = ?, FALSE)`, [
|
|
76417
|
+
this.rawQuotedIdentifier(key),
|
|
76112
76418
|
value
|
|
76113
76419
|
]);
|
|
76114
76420
|
}
|
|
76115
76421
|
});
|
|
76116
76422
|
}
|
|
76117
76423
|
if (filters.notEqual) {
|
|
76118
|
-
iterate(filters.notEqual, (q2, key, value) => {
|
|
76119
|
-
|
|
76424
|
+
iterate(filters.notEqual, "notEqual" /* NOT_EQUAL */, (q2, key, value) => {
|
|
76425
|
+
if (shouldOr) {
|
|
76426
|
+
q2 = q2.or;
|
|
76427
|
+
}
|
|
76120
76428
|
if (this.client === "mssql" /* MS_SQL */) {
|
|
76121
|
-
return q2[
|
|
76122
|
-
|
|
76123
|
-
|
|
76124
|
-
);
|
|
76429
|
+
return q2.whereRaw(`CASE WHEN ?? = ? THEN 1 ELSE 0 END = 0`, [
|
|
76430
|
+
this.rawQuotedIdentifier(key),
|
|
76431
|
+
value
|
|
76432
|
+
]);
|
|
76125
76433
|
} else if (this.client === "oracledb" /* ORACLE */) {
|
|
76126
76434
|
const identifier = this.convertClobs(key);
|
|
76127
|
-
return q2
|
|
76128
|
-
|
|
76129
|
-
|
|
76130
|
-
);
|
|
76435
|
+
return q2.where(
|
|
76436
|
+
(subq) => subq.not.whereNull(identifier).and.where(identifier, "!=", value)
|
|
76437
|
+
).or.whereNull(identifier);
|
|
76131
76438
|
} else {
|
|
76132
|
-
return q2
|
|
76439
|
+
return q2.whereRaw(`COALESCE(?? != ?, TRUE)`, [
|
|
76440
|
+
this.rawQuotedIdentifier(key),
|
|
76133
76441
|
value
|
|
76134
76442
|
]);
|
|
76135
76443
|
}
|
|
76136
76444
|
});
|
|
76137
76445
|
}
|
|
76138
76446
|
if (filters.empty) {
|
|
76139
|
-
iterate(filters.empty, (q2, key) => {
|
|
76140
|
-
|
|
76141
|
-
|
|
76447
|
+
iterate(filters.empty, "empty" /* EMPTY */, (q2, key) => {
|
|
76448
|
+
if (shouldOr) {
|
|
76449
|
+
q2 = q2.or;
|
|
76450
|
+
}
|
|
76451
|
+
return q2.whereNull(key);
|
|
76142
76452
|
});
|
|
76143
76453
|
}
|
|
76144
76454
|
if (filters.notEmpty) {
|
|
76145
|
-
iterate(filters.notEmpty, (q2, key) => {
|
|
76146
|
-
|
|
76147
|
-
|
|
76455
|
+
iterate(filters.notEmpty, "notEmpty" /* NOT_EMPTY */, (q2, key) => {
|
|
76456
|
+
if (shouldOr) {
|
|
76457
|
+
q2 = q2.or;
|
|
76458
|
+
}
|
|
76459
|
+
return q2.whereNotNull(key);
|
|
76148
76460
|
});
|
|
76149
76461
|
}
|
|
76150
76462
|
if (filters.contains) {
|
|
@@ -76213,7 +76525,7 @@ var InternalBuilder = class {
|
|
|
76213
76525
|
const selectFields = qualifiedFields.map(
|
|
76214
76526
|
(field) => this.convertClobs(field, { forSelect: true })
|
|
76215
76527
|
);
|
|
76216
|
-
query = query.
|
|
76528
|
+
query = query.groupBy(groupByFields).select(selectFields);
|
|
76217
76529
|
} else {
|
|
76218
76530
|
query = query.groupBy(qualifiedFields).select(qualifiedFields);
|
|
76219
76531
|
}
|
|
@@ -76225,11 +76537,10 @@ var InternalBuilder = class {
|
|
|
76225
76537
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76226
76538
|
const field = this.convertClobs(`${tableName}.${aggregation.field}`);
|
|
76227
76539
|
query = query.select(
|
|
76228
|
-
this.knex.raw(
|
|
76229
|
-
|
|
76230
|
-
|
|
76231
|
-
|
|
76232
|
-
)
|
|
76540
|
+
this.knex.raw(`COUNT(DISTINCT ??) as ??`, [
|
|
76541
|
+
field,
|
|
76542
|
+
aggregation.name
|
|
76543
|
+
])
|
|
76233
76544
|
);
|
|
76234
76545
|
} else {
|
|
76235
76546
|
query = query.countDistinct(
|
|
@@ -76284,9 +76595,11 @@ var InternalBuilder = class {
|
|
|
76284
76595
|
} else {
|
|
76285
76596
|
let composite = `${aliased}.${key}`;
|
|
76286
76597
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76287
|
-
query = query.orderByRaw(
|
|
76288
|
-
|
|
76289
|
-
|
|
76598
|
+
query = query.orderByRaw(`?? ?? nulls ??`, [
|
|
76599
|
+
this.convertClobs(composite),
|
|
76600
|
+
this.knex.raw(direction),
|
|
76601
|
+
this.knex.raw(nulls)
|
|
76602
|
+
]);
|
|
76290
76603
|
} else {
|
|
76291
76604
|
query = query.orderBy(composite, direction, nulls);
|
|
76292
76605
|
}
|
|
@@ -76308,17 +76621,18 @@ var InternalBuilder = class {
|
|
|
76308
76621
|
}
|
|
76309
76622
|
buildJsonField(field) {
|
|
76310
76623
|
const parts = field.split(".");
|
|
76311
|
-
let
|
|
76624
|
+
let unaliased;
|
|
76625
|
+
let tableField;
|
|
76312
76626
|
if (parts.length > 1) {
|
|
76313
76627
|
const alias = parts.shift();
|
|
76314
76628
|
unaliased = parts.join(".");
|
|
76315
|
-
tableField = `${
|
|
76629
|
+
tableField = `${alias}.${unaliased}`;
|
|
76316
76630
|
} else {
|
|
76317
76631
|
unaliased = parts.join(".");
|
|
76318
|
-
tableField =
|
|
76632
|
+
tableField = unaliased;
|
|
76319
76633
|
}
|
|
76320
76634
|
const separator = this.client === "oracledb" /* ORACLE */ ? " VALUE " : ",";
|
|
76321
|
-
return
|
|
76635
|
+
return this.knex.raw(`?${separator}??`, [unaliased, this.rawQuotedIdentifier(tableField)]).toString();
|
|
76322
76636
|
}
|
|
76323
76637
|
maxFunctionParameters() {
|
|
76324
76638
|
switch (this.client) {
|
|
@@ -76382,11 +76696,11 @@ var InternalBuilder = class {
|
|
|
76382
76696
|
subQuery = subQuery.where(
|
|
76383
76697
|
correlatedTo,
|
|
76384
76698
|
"=",
|
|
76385
|
-
|
|
76699
|
+
this.rawQuotedIdentifier(correlatedFrom)
|
|
76386
76700
|
);
|
|
76387
76701
|
const standardWrap = (select) => {
|
|
76388
76702
|
subQuery = subQuery.select(`${toAlias}.*`).limit(getRelationshipLimit());
|
|
76389
|
-
return knex3.select(
|
|
76703
|
+
return knex3.select(select).from({
|
|
76390
76704
|
[toAlias]: subQuery
|
|
76391
76705
|
});
|
|
76392
76706
|
};
|
|
@@ -76395,12 +76709,12 @@ var InternalBuilder = class {
|
|
|
76395
76709
|
case "sqlite3" /* SQL_LITE */:
|
|
76396
76710
|
subQuery = this.addJoinFieldCheck(subQuery, relationship);
|
|
76397
76711
|
wrapperQuery = standardWrap(
|
|
76398
|
-
`json_group_array(json_object(${fieldList}))`
|
|
76712
|
+
this.knex.raw(`json_group_array(json_object(${fieldList}))`)
|
|
76399
76713
|
);
|
|
76400
76714
|
break;
|
|
76401
76715
|
case "pg" /* POSTGRES */:
|
|
76402
76716
|
wrapperQuery = standardWrap(
|
|
76403
|
-
`json_agg(json_build_object(${fieldList}))`
|
|
76717
|
+
this.knex.raw(`json_agg(json_build_object(${fieldList}))`)
|
|
76404
76718
|
);
|
|
76405
76719
|
break;
|
|
76406
76720
|
case "mariadb" /* MARIADB */:
|
|
@@ -76413,16 +76727,19 @@ var InternalBuilder = class {
|
|
|
76413
76727
|
case "mysql2" /* MY_SQL */:
|
|
76414
76728
|
case "oracledb" /* ORACLE */:
|
|
76415
76729
|
wrapperQuery = standardWrap(
|
|
76416
|
-
`json_arrayagg(json_object(${fieldList}))`
|
|
76730
|
+
this.knex.raw(`json_arrayagg(json_object(${fieldList}))`)
|
|
76417
76731
|
);
|
|
76418
76732
|
break;
|
|
76419
|
-
case "mssql" /* MS_SQL */:
|
|
76733
|
+
case "mssql" /* MS_SQL */: {
|
|
76734
|
+
const comparatorQuery = knex3.select(`${fromAlias}.*`).from({
|
|
76735
|
+
[fromAlias]: subQuery.select(`${toAlias}.*`).limit(getRelationshipLimit())
|
|
76736
|
+
});
|
|
76420
76737
|
wrapperQuery = knex3.raw(
|
|
76421
|
-
`(SELECT
|
|
76422
|
-
|
|
76423
|
-
})} FOR JSON PATH))`
|
|
76738
|
+
`(SELECT ?? = (${comparatorQuery} FOR JSON PATH))`,
|
|
76739
|
+
[this.rawQuotedIdentifier(toAlias)]
|
|
76424
76740
|
);
|
|
76425
76741
|
break;
|
|
76742
|
+
}
|
|
76426
76743
|
default:
|
|
76427
76744
|
throw new Error(`JSON relationships not implement for ${sqlClient}`);
|
|
76428
76745
|
}
|