@budibase/backend-core 2.33.2 → 2.33.4
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 +566 -309
- 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/events/identification.js +7 -5
- package/dist/src/events/identification.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/index.d.ts +0 -2
- 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 +243 -160
- 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/dist/src/tenancy/db.d.ts +0 -3
- package/dist/src/tenancy/db.js +0 -31
- package/dist/src/tenancy/db.js.map +1 -1
- package/dist/src/users/db.d.ts +2 -2
- package/dist/src/users/db.js +7 -7
- package/dist/src/users/db.js.map +1 -1
- package/dist/src/users/users.d.ts +1 -0
- package/dist/src/users/users.js +13 -0
- package/dist/src/users/users.js.map +1 -1
- package/dist/src/users/utils.d.ts +3 -3
- package/dist/src/users/utils.js +5 -14
- package/dist/src/users/utils.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/events/identification.ts +7 -6
- 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 +290 -206
- package/src/sql/sqlTable.ts +4 -1
- package/src/tenancy/db.ts +0 -23
- package/src/users/db.ts +12 -9
- package/src/users/users.ts +11 -0
- package/src/users/utils.ts +12 -18
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;
|
|
@@ -67209,32 +67267,13 @@ __export(tenancy_exports, {
|
|
|
67209
67267
|
addTenantToUrl: () => addTenantToUrl,
|
|
67210
67268
|
getTenantDB: () => getTenantDB,
|
|
67211
67269
|
getTenantIDFromCtx: () => getTenantIDFromCtx,
|
|
67212
|
-
|
|
67213
|
-
isUserInAppTenant: () => isUserInAppTenant,
|
|
67214
|
-
saveTenantInfo: () => saveTenantInfo
|
|
67270
|
+
isUserInAppTenant: () => isUserInAppTenant
|
|
67215
67271
|
});
|
|
67216
67272
|
|
|
67217
67273
|
// src/tenancy/db.ts
|
|
67218
67274
|
function getTenantDB(tenantId) {
|
|
67219
67275
|
return getDB(getGlobalDBName(tenantId));
|
|
67220
67276
|
}
|
|
67221
|
-
async function saveTenantInfo(tenantInfo) {
|
|
67222
|
-
const db = getTenantDB(tenantInfo.tenantId);
|
|
67223
|
-
return db.put({
|
|
67224
|
-
_id: "tenant_info",
|
|
67225
|
-
...tenantInfo
|
|
67226
|
-
});
|
|
67227
|
-
}
|
|
67228
|
-
async function getTenantInfo(tenantId) {
|
|
67229
|
-
try {
|
|
67230
|
-
const db = getTenantDB(tenantId);
|
|
67231
|
-
const tenantInfo = await db.get("tenant_info");
|
|
67232
|
-
delete tenantInfo.owner.password;
|
|
67233
|
-
return tenantInfo;
|
|
67234
|
-
} catch {
|
|
67235
|
-
return void 0;
|
|
67236
|
-
}
|
|
67237
|
-
}
|
|
67238
67277
|
|
|
67239
67278
|
// src/tenancy/tenancy.ts
|
|
67240
67279
|
function addTenantToUrl(url) {
|
|
@@ -67726,12 +67765,13 @@ var FlagSet = class {
|
|
|
67726
67765
|
}
|
|
67727
67766
|
};
|
|
67728
67767
|
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),
|
|
67768
|
+
["DEFAULT_VALUES" /* DEFAULT_VALUES */]: Flag.boolean(environment_default.isDev()),
|
|
67769
|
+
["AUTOMATION_BRANCHING" /* AUTOMATION_BRANCHING */]: Flag.boolean(environment_default.isDev()),
|
|
67770
|
+
["SQS" /* SQS */]: Flag.boolean(true),
|
|
67732
67771
|
["AI_CUSTOM_CONFIGS" /* AI_CUSTOM_CONFIGS */]: Flag.boolean(environment_default.isDev()),
|
|
67733
67772
|
["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(environment_default.isDev()),
|
|
67734
|
-
["TABLES_DEFAULT_ADMIN" /* TABLES_DEFAULT_ADMIN */]: Flag.boolean(environment_default.isDev())
|
|
67773
|
+
["TABLES_DEFAULT_ADMIN" /* TABLES_DEFAULT_ADMIN */]: Flag.boolean(environment_default.isDev()),
|
|
67774
|
+
["BUDIBASE_AI" /* BUDIBASE_AI */]: Flag.boolean(environment_default.isDev())
|
|
67735
67775
|
});
|
|
67736
67776
|
|
|
67737
67777
|
// src/features/tests/utils.ts
|
|
@@ -68119,7 +68159,7 @@ var DatabaseImpl = class _DatabaseImpl {
|
|
|
68119
68159
|
});
|
|
68120
68160
|
}
|
|
68121
68161
|
async destroy() {
|
|
68122
|
-
if (await flags.isEnabled("SQS") && await this.exists(SQLITE_DESIGN_DOC_ID)) {
|
|
68162
|
+
if (await flags.isEnabled("SQS" /* SQS */) && await this.exists(SQLITE_DESIGN_DOC_ID)) {
|
|
68123
68163
|
const definition = await this.get(SQLITE_DESIGN_DOC_ID);
|
|
68124
68164
|
definition.sql.tables = {};
|
|
68125
68165
|
await this.put(definition);
|
|
@@ -69065,8 +69105,9 @@ __export(users_exports3, {
|
|
|
69065
69105
|
bulkUpdateGlobalUsers: () => bulkUpdateGlobalUsers,
|
|
69066
69106
|
cleanseUserObject: () => cleanseUserObject,
|
|
69067
69107
|
doesUserExist: () => doesUserExist,
|
|
69068
|
-
|
|
69108
|
+
getAccountHolderFromUsers: () => getAccountHolderFromUsers,
|
|
69069
69109
|
getAllUserIds: () => getAllUserIds,
|
|
69110
|
+
getAllUsers: () => getAllUsers,
|
|
69070
69111
|
getById: () => getById,
|
|
69071
69112
|
getCreatorCount: () => getCreatorCount,
|
|
69072
69113
|
getExistingAccounts: () => getExistingAccounts,
|
|
@@ -69098,7 +69139,7 @@ __export(users_exports3, {
|
|
|
69098
69139
|
// src/users/utils.ts
|
|
69099
69140
|
var utils_exports6 = {};
|
|
69100
69141
|
__export(utils_exports6, {
|
|
69101
|
-
|
|
69142
|
+
getAccountHolderFromUsers: () => getAccountHolderFromUsers,
|
|
69102
69143
|
hasAdminPermissions: () => hasAdminPermissions2,
|
|
69103
69144
|
hasAppBuilderPermissions: () => hasAppBuilderPermissions2,
|
|
69104
69145
|
hasBuilderPermissions: () => hasBuilderPermissions2,
|
|
@@ -69321,27 +69362,35 @@ var EmailUnavailableError = class extends Error {
|
|
|
69321
69362
|
};
|
|
69322
69363
|
|
|
69323
69364
|
// src/security/roles.ts
|
|
69324
|
-
var
|
|
69325
|
-
__export(
|
|
69365
|
+
var roles_exports2 = {};
|
|
69366
|
+
__export(roles_exports2, {
|
|
69326
69367
|
AccessController: () => AccessController,
|
|
69327
69368
|
BUILTIN_ROLE_IDS: () => BUILTIN_ROLE_IDS,
|
|
69328
|
-
Role: () =>
|
|
69369
|
+
Role: () => Role2,
|
|
69370
|
+
RoleHierarchyTraversal: () => RoleHierarchyTraversal,
|
|
69329
69371
|
RoleIDVersion: () => RoleIDVersion,
|
|
69330
69372
|
builtinRoleToNumber: () => builtinRoleToNumber,
|
|
69331
69373
|
checkForRoleResourceArray: () => checkForRoleResourceArray,
|
|
69374
|
+
compareRoleIds: () => compareRoleIds,
|
|
69375
|
+
externalRole: () => externalRole,
|
|
69376
|
+
findRole: () => findRole,
|
|
69332
69377
|
getAllRoleIds: () => getAllRoleIds,
|
|
69333
69378
|
getAllRoles: () => getAllRoles,
|
|
69334
69379
|
getBuiltinRole: () => getBuiltinRole,
|
|
69335
69380
|
getBuiltinRoles: () => getBuiltinRoles,
|
|
69336
69381
|
getDBRoleID: () => getDBRoleID,
|
|
69337
69382
|
getExternalRoleID: () => getExternalRoleID,
|
|
69383
|
+
getExternalRoleIDs: () => getExternalRoleIDs,
|
|
69338
69384
|
getRole: () => getRole,
|
|
69339
69385
|
getUserRoleHierarchy: () => getUserRoleHierarchy,
|
|
69340
69386
|
getUserRoleIdHierarchy: () => getUserRoleIdHierarchy,
|
|
69341
69387
|
isBuiltin: () => isBuiltin,
|
|
69342
69388
|
lowerBuiltinRoleID: () => lowerBuiltinRoleID,
|
|
69343
|
-
|
|
69389
|
+
prefixRoleIDNoBuiltin: () => prefixRoleIDNoBuiltin,
|
|
69390
|
+
roleToNumber: () => roleToNumber,
|
|
69391
|
+
saveRoles: () => saveRoles
|
|
69344
69392
|
});
|
|
69393
|
+
var import_semver = __toESM(require("semver"));
|
|
69345
69394
|
|
|
69346
69395
|
// src/security/permissions.ts
|
|
69347
69396
|
var permissions_exports = {};
|
|
@@ -69493,6 +69542,7 @@ var GLOBAL_BUILDER = "globalBuilder" /* GLOBAL_BUILDER */;
|
|
|
69493
69542
|
|
|
69494
69543
|
// src/security/roles.ts
|
|
69495
69544
|
var import_cloneDeep2 = __toESM(require("lodash/fp/cloneDeep"));
|
|
69545
|
+
var import_lodash4 = require("lodash");
|
|
69496
69546
|
var BUILTIN_ROLE_IDS = {
|
|
69497
69547
|
ADMIN: "ADMIN",
|
|
69498
69548
|
POWER: "POWER",
|
|
@@ -69503,19 +69553,20 @@ var BUILTIN_IDS = {
|
|
|
69503
69553
|
...BUILTIN_ROLE_IDS,
|
|
69504
69554
|
BUILDER: "BUILDER"
|
|
69505
69555
|
};
|
|
69506
|
-
var EXTERNAL_BUILTIN_ROLE_IDS = [
|
|
69507
|
-
BUILTIN_IDS.ADMIN,
|
|
69508
|
-
BUILTIN_IDS.POWER,
|
|
69509
|
-
BUILTIN_IDS.BASIC,
|
|
69510
|
-
BUILTIN_IDS.PUBLIC
|
|
69511
|
-
];
|
|
69512
69556
|
var RoleIDVersion = {
|
|
69513
69557
|
// original version, with a UUID based ID
|
|
69514
69558
|
UUID: void 0,
|
|
69515
69559
|
// new version - with name based ID
|
|
69516
69560
|
NAME: "name"
|
|
69517
69561
|
};
|
|
69518
|
-
|
|
69562
|
+
function rolesInList(roleIds, ids) {
|
|
69563
|
+
if (Array.isArray(ids)) {
|
|
69564
|
+
return ids.filter((id) => roleIds.includes(id)).length === ids.length;
|
|
69565
|
+
} else {
|
|
69566
|
+
return roleIds.includes(ids);
|
|
69567
|
+
}
|
|
69568
|
+
}
|
|
69569
|
+
var Role2 = class {
|
|
69519
69570
|
constructor(id, name, permissionId, uiMetadata) {
|
|
69520
69571
|
this.permissions = {};
|
|
69521
69572
|
this._id = id;
|
|
@@ -69525,12 +69576,57 @@ var Role = class {
|
|
|
69525
69576
|
this.version = RoleIDVersion.NAME;
|
|
69526
69577
|
}
|
|
69527
69578
|
addInheritance(inherits) {
|
|
69579
|
+
if (inherits && typeof inherits === "string") {
|
|
69580
|
+
inherits = prefixRoleIDNoBuiltin(inherits);
|
|
69581
|
+
} else if (inherits && Array.isArray(inherits)) {
|
|
69582
|
+
inherits = inherits.map(prefixRoleIDNoBuiltin);
|
|
69583
|
+
}
|
|
69528
69584
|
this.inherits = inherits;
|
|
69529
69585
|
return this;
|
|
69530
69586
|
}
|
|
69531
69587
|
};
|
|
69588
|
+
var RoleHierarchyTraversal = class {
|
|
69589
|
+
constructor(allRoles, opts) {
|
|
69590
|
+
this.allRoles = allRoles;
|
|
69591
|
+
this.opts = opts;
|
|
69592
|
+
}
|
|
69593
|
+
walk(role) {
|
|
69594
|
+
const opts = this.opts, allRoles = this.allRoles;
|
|
69595
|
+
let roleList = [];
|
|
69596
|
+
if (!role || !role._id) {
|
|
69597
|
+
return roleList;
|
|
69598
|
+
}
|
|
69599
|
+
roleList.push(role);
|
|
69600
|
+
if (Array.isArray(role.inherits)) {
|
|
69601
|
+
for (let roleId of role.inherits) {
|
|
69602
|
+
const foundRole = findRole(roleId, allRoles, opts);
|
|
69603
|
+
if (foundRole) {
|
|
69604
|
+
roleList = roleList.concat(this.walk(foundRole));
|
|
69605
|
+
}
|
|
69606
|
+
}
|
|
69607
|
+
} else {
|
|
69608
|
+
const foundRoleIds = [];
|
|
69609
|
+
let currentRole = role;
|
|
69610
|
+
while (currentRole && currentRole.inherits && !rolesInList(foundRoleIds, currentRole.inherits)) {
|
|
69611
|
+
if (Array.isArray(currentRole.inherits)) {
|
|
69612
|
+
return roleList.concat(this.walk(currentRole));
|
|
69613
|
+
} else {
|
|
69614
|
+
foundRoleIds.push(currentRole.inherits);
|
|
69615
|
+
currentRole = findRole(currentRole.inherits, allRoles, opts);
|
|
69616
|
+
if (currentRole) {
|
|
69617
|
+
roleList.push(currentRole);
|
|
69618
|
+
}
|
|
69619
|
+
}
|
|
69620
|
+
if (helpers_exports.roles.checkForRoleInheritanceLoops(roleList)) {
|
|
69621
|
+
break;
|
|
69622
|
+
}
|
|
69623
|
+
}
|
|
69624
|
+
}
|
|
69625
|
+
return (0, import_lodash4.uniqBy)(roleList, (role2) => role2._id);
|
|
69626
|
+
}
|
|
69627
|
+
};
|
|
69532
69628
|
var BUILTIN_ROLES = {
|
|
69533
|
-
ADMIN: new
|
|
69629
|
+
ADMIN: new Role2(
|
|
69534
69630
|
BUILTIN_IDS.ADMIN,
|
|
69535
69631
|
BUILTIN_IDS.ADMIN,
|
|
69536
69632
|
"admin" /* ADMIN */,
|
|
@@ -69540,7 +69636,7 @@ var BUILTIN_ROLES = {
|
|
|
69540
69636
|
color: "var(--spectrum-global-color-static-red-400)" /* ADMIN */
|
|
69541
69637
|
}
|
|
69542
69638
|
).addInheritance(BUILTIN_IDS.POWER),
|
|
69543
|
-
POWER: new
|
|
69639
|
+
POWER: new Role2(
|
|
69544
69640
|
BUILTIN_IDS.POWER,
|
|
69545
69641
|
BUILTIN_IDS.POWER,
|
|
69546
69642
|
"power" /* POWER */,
|
|
@@ -69550,7 +69646,7 @@ var BUILTIN_ROLES = {
|
|
|
69550
69646
|
color: "var(--spectrum-global-color-static-orange-400)" /* POWER */
|
|
69551
69647
|
}
|
|
69552
69648
|
).addInheritance(BUILTIN_IDS.BASIC),
|
|
69553
|
-
BASIC: new
|
|
69649
|
+
BASIC: new Role2(
|
|
69554
69650
|
BUILTIN_IDS.BASIC,
|
|
69555
69651
|
BUILTIN_IDS.BASIC,
|
|
69556
69652
|
"write" /* WRITE */,
|
|
@@ -69560,7 +69656,7 @@ var BUILTIN_ROLES = {
|
|
|
69560
69656
|
color: "var(--spectrum-global-color-static-green-400)" /* BASIC */
|
|
69561
69657
|
}
|
|
69562
69658
|
).addInheritance(BUILTIN_IDS.PUBLIC),
|
|
69563
|
-
PUBLIC: new
|
|
69659
|
+
PUBLIC: new Role2(
|
|
69564
69660
|
BUILTIN_IDS.PUBLIC,
|
|
69565
69661
|
BUILTIN_IDS.PUBLIC,
|
|
69566
69662
|
"public" /* PUBLIC */,
|
|
@@ -69570,7 +69666,7 @@ var BUILTIN_ROLES = {
|
|
|
69570
69666
|
color: "var(--spectrum-global-color-static-blue-400)" /* PUBLIC */
|
|
69571
69667
|
}
|
|
69572
69668
|
),
|
|
69573
|
-
BUILDER: new
|
|
69669
|
+
BUILDER: new Role2(
|
|
69574
69670
|
BUILTIN_IDS.BUILDER,
|
|
69575
69671
|
BUILTIN_IDS.BUILDER,
|
|
69576
69672
|
"admin" /* ADMIN */,
|
|
@@ -69585,7 +69681,14 @@ function getBuiltinRoles() {
|
|
|
69585
69681
|
return (0, import_cloneDeep2.default)(BUILTIN_ROLES);
|
|
69586
69682
|
}
|
|
69587
69683
|
function isBuiltin(role) {
|
|
69588
|
-
return
|
|
69684
|
+
return Object.values(BUILTIN_ROLE_IDS).includes(role);
|
|
69685
|
+
}
|
|
69686
|
+
function prefixRoleIDNoBuiltin(roleId) {
|
|
69687
|
+
if (isBuiltin(roleId)) {
|
|
69688
|
+
return roleId;
|
|
69689
|
+
} else {
|
|
69690
|
+
return prefixRoleID(roleId);
|
|
69691
|
+
}
|
|
69589
69692
|
}
|
|
69590
69693
|
function getBuiltinRole(roleId) {
|
|
69591
69694
|
const role = Object.values(BUILTIN_ROLES).find(
|
|
@@ -69607,7 +69710,11 @@ function builtinRoleToNumber(id) {
|
|
|
69607
69710
|
if (!role) {
|
|
69608
69711
|
break;
|
|
69609
69712
|
}
|
|
69610
|
-
|
|
69713
|
+
if (Array.isArray(role.inherits)) {
|
|
69714
|
+
throw new Error("Built-in roles don't support multi-inheritance");
|
|
69715
|
+
} else {
|
|
69716
|
+
role = builtins[role.inherits];
|
|
69717
|
+
}
|
|
69611
69718
|
count++;
|
|
69612
69719
|
} while (role !== null);
|
|
69613
69720
|
return count;
|
|
@@ -69619,12 +69726,26 @@ async function roleToNumber(id) {
|
|
|
69619
69726
|
const hierarchy = await getUserRoleHierarchy(id, {
|
|
69620
69727
|
defaultPublic: true
|
|
69621
69728
|
});
|
|
69622
|
-
|
|
69623
|
-
if (role
|
|
69729
|
+
const findNumber = (role) => {
|
|
69730
|
+
if (!role.inherits) {
|
|
69731
|
+
return 0;
|
|
69732
|
+
}
|
|
69733
|
+
if (Array.isArray(role.inherits)) {
|
|
69734
|
+
const highestBuiltin = role.inherits.map((roleId) => {
|
|
69735
|
+
const foundRole = hierarchy.find((role2) => role2._id === roleId);
|
|
69736
|
+
if (foundRole) {
|
|
69737
|
+
return findNumber(foundRole) + 1;
|
|
69738
|
+
}
|
|
69739
|
+
}).filter((number) => number).sort().pop();
|
|
69740
|
+
if (highestBuiltin != void 0) {
|
|
69741
|
+
return highestBuiltin;
|
|
69742
|
+
}
|
|
69743
|
+
} else if (isBuiltin(role.inherits)) {
|
|
69624
69744
|
return builtinRoleToNumber(role.inherits) + 1;
|
|
69625
69745
|
}
|
|
69626
|
-
|
|
69627
|
-
|
|
69746
|
+
return 0;
|
|
69747
|
+
};
|
|
69748
|
+
return Math.max(...hierarchy.map(findNumber));
|
|
69628
69749
|
}
|
|
69629
69750
|
function lowerBuiltinRoleID(roleId1, roleId2) {
|
|
69630
69751
|
if (!roleId1) {
|
|
@@ -69635,39 +69756,67 @@ function lowerBuiltinRoleID(roleId1, roleId2) {
|
|
|
69635
69756
|
}
|
|
69636
69757
|
return builtinRoleToNumber(roleId1) > builtinRoleToNumber(roleId2) ? roleId2 : roleId1;
|
|
69637
69758
|
}
|
|
69638
|
-
|
|
69759
|
+
function compareRoleIds(roleId1, roleId2) {
|
|
69760
|
+
return prefixRoleID(roleId1) === prefixRoleID(roleId2);
|
|
69761
|
+
}
|
|
69762
|
+
function externalRole(role) {
|
|
69763
|
+
let _id;
|
|
69764
|
+
if (role._id) {
|
|
69765
|
+
_id = getExternalRoleID(role._id);
|
|
69766
|
+
}
|
|
69767
|
+
return {
|
|
69768
|
+
...role,
|
|
69769
|
+
_id,
|
|
69770
|
+
inherits: getExternalRoleIDs(role.inherits, role.version)
|
|
69771
|
+
};
|
|
69772
|
+
}
|
|
69773
|
+
function findRole(roleId, roles, opts) {
|
|
69639
69774
|
let role = getBuiltinRole(roleId);
|
|
69640
69775
|
if (!role) {
|
|
69641
69776
|
roleId = prefixRoleID(roleId);
|
|
69642
69777
|
}
|
|
69643
|
-
|
|
69644
|
-
|
|
69645
|
-
|
|
69646
|
-
|
|
69778
|
+
const dbRole = roles.find(
|
|
69779
|
+
(role2) => role2._id && compareRoleIds(role2._id, roleId)
|
|
69780
|
+
);
|
|
69781
|
+
if (!dbRole && !isBuiltin(roleId) && opts?.defaultPublic) {
|
|
69782
|
+
return (0, import_cloneDeep2.default)(BUILTIN_ROLES.PUBLIC);
|
|
69783
|
+
}
|
|
69784
|
+
role = Object.assign(role || {}, dbRole);
|
|
69785
|
+
if (role?._id) {
|
|
69647
69786
|
role._id = getExternalRoleID(role._id, role.version);
|
|
69648
|
-
}
|
|
69649
|
-
|
|
69650
|
-
|
|
69651
|
-
|
|
69652
|
-
|
|
69653
|
-
|
|
69787
|
+
}
|
|
69788
|
+
return Object.keys(role).length === 0 ? void 0 : role;
|
|
69789
|
+
}
|
|
69790
|
+
async function getRole(roleId, opts) {
|
|
69791
|
+
const db = getAppDB();
|
|
69792
|
+
const roleList = [];
|
|
69793
|
+
if (!isBuiltin(roleId)) {
|
|
69794
|
+
const role = await db.tryGet(getDBRoleID(roleId));
|
|
69795
|
+
if (role) {
|
|
69796
|
+
roleList.push(role);
|
|
69654
69797
|
}
|
|
69655
69798
|
}
|
|
69656
|
-
return
|
|
69799
|
+
return findRole(roleId, roleList, opts);
|
|
69800
|
+
}
|
|
69801
|
+
async function saveRoles(roles) {
|
|
69802
|
+
const db = getAppDB();
|
|
69803
|
+
await db.bulkDocs(
|
|
69804
|
+
roles.filter((role) => role._id).map((role) => ({
|
|
69805
|
+
...role,
|
|
69806
|
+
_id: prefixRoleID(role._id)
|
|
69807
|
+
}))
|
|
69808
|
+
);
|
|
69657
69809
|
}
|
|
69658
69810
|
async function getAllUserRoles(userRoleId, opts) {
|
|
69811
|
+
const allRoles = await getAllRoles();
|
|
69659
69812
|
if (userRoleId === BUILTIN_IDS.ADMIN) {
|
|
69660
|
-
return
|
|
69813
|
+
return allRoles;
|
|
69661
69814
|
}
|
|
69662
|
-
|
|
69663
|
-
let roles =
|
|
69664
|
-
|
|
69665
|
-
|
|
69666
|
-
|
|
69667
|
-
currentRole = await getRole(currentRole.inherits);
|
|
69668
|
-
if (currentRole) {
|
|
69669
|
-
roles.push(currentRole);
|
|
69670
|
-
}
|
|
69815
|
+
const foundRole = findRole(userRoleId, allRoles, opts);
|
|
69816
|
+
let roles = [];
|
|
69817
|
+
if (foundRole) {
|
|
69818
|
+
const traversal = new RoleHierarchyTraversal(allRoles, opts);
|
|
69819
|
+
roles = traversal.walk(foundRole);
|
|
69671
69820
|
}
|
|
69672
69821
|
return roles;
|
|
69673
69822
|
}
|
|
@@ -69717,7 +69866,22 @@ async function getAllRoles(appId) {
|
|
|
69717
69866
|
);
|
|
69718
69867
|
}
|
|
69719
69868
|
const builtinRoles = getBuiltinRoles();
|
|
69720
|
-
|
|
69869
|
+
let externalBuiltinRoles = [];
|
|
69870
|
+
if (!db || await shouldIncludePowerRole(db)) {
|
|
69871
|
+
externalBuiltinRoles = [
|
|
69872
|
+
BUILTIN_IDS.ADMIN,
|
|
69873
|
+
BUILTIN_IDS.POWER,
|
|
69874
|
+
BUILTIN_IDS.BASIC,
|
|
69875
|
+
BUILTIN_IDS.PUBLIC
|
|
69876
|
+
];
|
|
69877
|
+
} else {
|
|
69878
|
+
externalBuiltinRoles = [
|
|
69879
|
+
BUILTIN_IDS.ADMIN,
|
|
69880
|
+
BUILTIN_IDS.BASIC,
|
|
69881
|
+
BUILTIN_IDS.PUBLIC
|
|
69882
|
+
];
|
|
69883
|
+
}
|
|
69884
|
+
for (let builtinRoleId of externalBuiltinRoles) {
|
|
69721
69885
|
const builtinRole = builtinRoles[builtinRoleId];
|
|
69722
69886
|
const dbBuiltin = roles.filter(
|
|
69723
69887
|
(dbRole) => getExternalRoleID(dbRole._id, dbRole.version) === builtinRoleId
|
|
@@ -69744,6 +69908,15 @@ async function getAllRoles(appId) {
|
|
|
69744
69908
|
return roles;
|
|
69745
69909
|
}
|
|
69746
69910
|
}
|
|
69911
|
+
async function shouldIncludePowerRole(db) {
|
|
69912
|
+
const app = await db.tryGet("app_metadata" /* APP_METADATA */);
|
|
69913
|
+
const creationVersion = app?.creationVersion;
|
|
69914
|
+
if (!creationVersion || !import_semver.default.valid(creationVersion)) {
|
|
69915
|
+
return true;
|
|
69916
|
+
}
|
|
69917
|
+
const isGreaterThan3x = import_semver.default.gte(creationVersion, "3.0.0");
|
|
69918
|
+
return !isGreaterThan3x;
|
|
69919
|
+
}
|
|
69747
69920
|
var AccessController = class {
|
|
69748
69921
|
constructor() {
|
|
69749
69922
|
this.userHierarchies = {};
|
|
@@ -69757,7 +69930,7 @@ var AccessController = class {
|
|
|
69757
69930
|
roleIds = await getUserRoleIdHierarchy(userRoleId);
|
|
69758
69931
|
this.userHierarchies[userRoleId] = roleIds;
|
|
69759
69932
|
}
|
|
69760
|
-
return roleIds?.
|
|
69933
|
+
return roleIds?.find((roleId) => compareRoleIds(roleId, tryingRoleId)) !== void 0;
|
|
69761
69934
|
}
|
|
69762
69935
|
async checkScreensAccess(screens, userRoleId) {
|
|
69763
69936
|
let accessibleScreens = [];
|
|
@@ -69784,13 +69957,22 @@ function getDBRoleID(roleName) {
|
|
|
69784
69957
|
return prefixRoleID(roleName);
|
|
69785
69958
|
}
|
|
69786
69959
|
function getExternalRoleID(roleId, version) {
|
|
69787
|
-
if (roleId.startsWith("role" /* ROLE */) && (isBuiltin(roleId) || version === RoleIDVersion.NAME)) {
|
|
69960
|
+
if (roleId.startsWith(`${"role" /* ROLE */}${SEPARATOR}`) && (isBuiltin(roleId) || version === RoleIDVersion.NAME)) {
|
|
69788
69961
|
const parts = roleId.split(SEPARATOR);
|
|
69789
69962
|
parts.shift();
|
|
69790
69963
|
return parts.join(SEPARATOR);
|
|
69791
69964
|
}
|
|
69792
69965
|
return roleId;
|
|
69793
69966
|
}
|
|
69967
|
+
function getExternalRoleIDs(roleIds, version) {
|
|
69968
|
+
if (!roleIds) {
|
|
69969
|
+
return roleIds;
|
|
69970
|
+
} else if (typeof roleIds === "string") {
|
|
69971
|
+
return getExternalRoleID(roleIds, version);
|
|
69972
|
+
} else {
|
|
69973
|
+
return roleIds.map((roleId) => getExternalRoleID(roleId, version));
|
|
69974
|
+
}
|
|
69975
|
+
}
|
|
69794
69976
|
|
|
69795
69977
|
// src/users/utils.ts
|
|
69796
69978
|
var isBuilder2 = sdk_exports.users.isBuilder;
|
|
@@ -69842,17 +70024,14 @@ async function validateUniqueUser(email, tenantId) {
|
|
|
69842
70024
|
}
|
|
69843
70025
|
}
|
|
69844
70026
|
}
|
|
69845
|
-
async function
|
|
70027
|
+
async function getAccountHolderFromUsers(users) {
|
|
69846
70028
|
if (!environment_default.SELF_HOSTED && !environment_default.DISABLE_ACCOUNT_PORTAL) {
|
|
69847
|
-
const
|
|
69848
|
-
|
|
69849
|
-
|
|
69850
|
-
|
|
69851
|
-
|
|
69852
|
-
|
|
69853
|
-
if (userIds.includes(budibaseUserId)) {
|
|
69854
|
-
return account;
|
|
69855
|
-
}
|
|
70029
|
+
const accountMetadata = await getExistingAccounts(
|
|
70030
|
+
users.map((user) => user.email)
|
|
70031
|
+
);
|
|
70032
|
+
return users.find(
|
|
70033
|
+
(user) => accountMetadata.map((metadata) => metadata.email).includes(user.email)
|
|
70034
|
+
);
|
|
69856
70035
|
}
|
|
69857
70036
|
}
|
|
69858
70037
|
|
|
@@ -70590,7 +70769,7 @@ __export(installation_exports, {
|
|
|
70590
70769
|
getInstall: () => getInstall,
|
|
70591
70770
|
getInstallFromDB: () => getInstallFromDB
|
|
70592
70771
|
});
|
|
70593
|
-
var
|
|
70772
|
+
var import_semver2 = __toESM(require("semver"));
|
|
70594
70773
|
var getInstall = async () => {
|
|
70595
70774
|
return withCache("installation" /* INSTALLATION */, 86400 /* ONE_DAY */, getInstallFromDB, {
|
|
70596
70775
|
useTenancy: false
|
|
@@ -70659,8 +70838,8 @@ var checkInstallVersion = async () => {
|
|
|
70659
70838
|
const newVersion = environment_default.VERSION;
|
|
70660
70839
|
try {
|
|
70661
70840
|
if (currentVersion !== newVersion) {
|
|
70662
|
-
const isUpgrade =
|
|
70663
|
-
const isDowngrade =
|
|
70841
|
+
const isUpgrade = import_semver2.default.gt(newVersion, currentVersion);
|
|
70842
|
+
const isDowngrade = import_semver2.default.lt(newVersion, currentVersion);
|
|
70664
70843
|
const success = await updateVersion(newVersion);
|
|
70665
70844
|
if (success) {
|
|
70666
70845
|
await doInIdentityContext(
|
|
@@ -70799,8 +70978,9 @@ var identifyUser = async (user, account, timestamp) => {
|
|
|
70799
70978
|
if (isSSOUser(user)) {
|
|
70800
70979
|
providerType = user.providerType;
|
|
70801
70980
|
}
|
|
70802
|
-
const accountHolder =
|
|
70803
|
-
const
|
|
70981
|
+
const accountHolder = await getExistingAccounts([user.email]);
|
|
70982
|
+
const isAccountHolder = accountHolder.length > 0;
|
|
70983
|
+
const verified2 = !!account && isAccountHolder && account.verified;
|
|
70804
70984
|
const installationId = await getInstallationId();
|
|
70805
70985
|
const hosting = account ? account.hosting : getHostingFromEnv();
|
|
70806
70986
|
const environment2 = getDeploymentEnvironment();
|
|
@@ -70811,7 +70991,7 @@ var identifyUser = async (user, account, timestamp) => {
|
|
|
70811
70991
|
installationId,
|
|
70812
70992
|
tenantId,
|
|
70813
70993
|
verified: verified2,
|
|
70814
|
-
accountHolder,
|
|
70994
|
+
accountHolder: isAccountHolder,
|
|
70815
70995
|
providerType,
|
|
70816
70996
|
builder,
|
|
70817
70997
|
admin,
|
|
@@ -70830,8 +71010,9 @@ var identifyAccount = async (account) => {
|
|
|
70830
71010
|
const installationId = await getInstallationId();
|
|
70831
71011
|
const environment2 = getDeploymentEnvironment();
|
|
70832
71012
|
if (isCloudAccount(account)) {
|
|
70833
|
-
|
|
70834
|
-
|
|
71013
|
+
const user = await getGlobalUserByEmail(account.email);
|
|
71014
|
+
if (user?._id) {
|
|
71015
|
+
id = user._id;
|
|
70835
71016
|
}
|
|
70836
71017
|
}
|
|
70837
71018
|
const identity = {
|
|
@@ -72816,24 +72997,24 @@ var UserDB = class _UserDB {
|
|
|
72816
72997
|
}
|
|
72817
72998
|
);
|
|
72818
72999
|
}
|
|
72819
|
-
static async bulkDelete(
|
|
73000
|
+
static async bulkDelete(users) {
|
|
72820
73001
|
const db = getGlobalDB();
|
|
72821
73002
|
const response = {
|
|
72822
73003
|
successful: [],
|
|
72823
73004
|
unsuccessful: []
|
|
72824
73005
|
};
|
|
72825
|
-
const
|
|
72826
|
-
if (
|
|
72827
|
-
|
|
73006
|
+
const accountHolder = await getAccountHolderFromUsers(users);
|
|
73007
|
+
if (accountHolder) {
|
|
73008
|
+
users = users.filter((u) => u.userId !== accountHolder.userId);
|
|
72828
73009
|
response.unsuccessful.push({
|
|
72829
|
-
_id:
|
|
72830
|
-
email:
|
|
73010
|
+
_id: accountHolder.userId,
|
|
73011
|
+
email: accountHolder.email,
|
|
72831
73012
|
reason: "Account holder cannot be deleted"
|
|
72832
73013
|
});
|
|
72833
73014
|
}
|
|
72834
73015
|
const allDocsResponse = await db.allDocs({
|
|
72835
73016
|
include_docs: true,
|
|
72836
|
-
keys:
|
|
73017
|
+
keys: users.map((u) => u.userId)
|
|
72837
73018
|
});
|
|
72838
73019
|
const usersToDelete = allDocsResponse.rows.map((user) => {
|
|
72839
73020
|
return user.doc;
|
|
@@ -72980,6 +73161,16 @@ async function getAllUserIds() {
|
|
|
72980
73161
|
});
|
|
72981
73162
|
return response.rows.map((row) => row.id);
|
|
72982
73163
|
}
|
|
73164
|
+
async function getAllUsers() {
|
|
73165
|
+
const db = getGlobalDB();
|
|
73166
|
+
const startKey = `${"us" /* USER */}${SEPARATOR}`;
|
|
73167
|
+
const response = await db.allDocs({
|
|
73168
|
+
startkey: startKey,
|
|
73169
|
+
endkey: `${startKey}${UNICODE_MAX}`,
|
|
73170
|
+
include_docs: true
|
|
73171
|
+
});
|
|
73172
|
+
return response.rows.map((row) => row.doc);
|
|
73173
|
+
}
|
|
72983
73174
|
async function bulkUpdateGlobalUsers(users) {
|
|
72984
73175
|
const db = getGlobalDB();
|
|
72985
73176
|
return await db.bulkDocs(users);
|
|
@@ -74435,6 +74626,7 @@ function timeMinusOneMinute() {
|
|
|
74435
74626
|
function finalise(ctx, opts = {}) {
|
|
74436
74627
|
ctx.publicEndpoint = opts.publicEndpoint || false;
|
|
74437
74628
|
ctx.isAuthenticated = opts.authenticated || false;
|
|
74629
|
+
ctx.loginMethod = opts.loginMethod;
|
|
74438
74630
|
ctx.user = opts.user;
|
|
74439
74631
|
ctx.internal = opts.internal || false;
|
|
74440
74632
|
ctx.version = opts.version;
|
|
@@ -74492,7 +74684,7 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74492
74684
|
apiKey = ctx.request.headers["authorization" /* AUTHORIZATION */].split(" ")[1];
|
|
74493
74685
|
}
|
|
74494
74686
|
const tenantId = ctx.request.headers["x-budibase-tenant-id" /* TENANT_ID */];
|
|
74495
|
-
let authenticated = false, user =
|
|
74687
|
+
let authenticated = false, user = void 0, internal = false, loginMethod = void 0;
|
|
74496
74688
|
if (authCookie && !apiKey) {
|
|
74497
74689
|
const sessionId = authCookie.sessionId;
|
|
74498
74690
|
const userId = authCookie.userId;
|
|
@@ -74514,6 +74706,7 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74514
74706
|
});
|
|
74515
74707
|
}
|
|
74516
74708
|
user.csrfToken = session.csrfToken;
|
|
74709
|
+
loginMethod = "cookie" /* COOKIE */;
|
|
74517
74710
|
if (session?.lastAccessedAt < timeMinusOneMinute()) {
|
|
74518
74711
|
await updateSessionTTL(session);
|
|
74519
74712
|
}
|
|
@@ -74530,17 +74723,16 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74530
74723
|
apiKey,
|
|
74531
74724
|
populateUser
|
|
74532
74725
|
);
|
|
74533
|
-
if (valid
|
|
74726
|
+
if (valid) {
|
|
74534
74727
|
authenticated = true;
|
|
74728
|
+
loginMethod = "api_key" /* API_KEY */;
|
|
74535
74729
|
user = foundUser;
|
|
74536
|
-
|
|
74537
|
-
authenticated = true;
|
|
74538
|
-
internal = true;
|
|
74730
|
+
internal = !foundUser;
|
|
74539
74731
|
}
|
|
74540
74732
|
}
|
|
74541
74733
|
if (!user && tenantId) {
|
|
74542
74734
|
user = { tenantId };
|
|
74543
|
-
} else if (user) {
|
|
74735
|
+
} else if (user && "password" in user) {
|
|
74544
74736
|
delete user.password;
|
|
74545
74737
|
}
|
|
74546
74738
|
if (!authenticated) {
|
|
@@ -74557,7 +74749,14 @@ function authenticated_default(noAuthPatterns = [], opts = {
|
|
|
74557
74749
|
status: user.status
|
|
74558
74750
|
});
|
|
74559
74751
|
}
|
|
74560
|
-
finalise(ctx, {
|
|
74752
|
+
finalise(ctx, {
|
|
74753
|
+
authenticated,
|
|
74754
|
+
user,
|
|
74755
|
+
internal,
|
|
74756
|
+
version,
|
|
74757
|
+
publicEndpoint,
|
|
74758
|
+
loginMethod
|
|
74759
|
+
});
|
|
74561
74760
|
if (isUser(user)) {
|
|
74562
74761
|
return doInUserContext(user, ctx, next);
|
|
74563
74762
|
} else {
|
|
@@ -75294,7 +75493,7 @@ var import_knex2 = require("knex");
|
|
|
75294
75493
|
// src/sql/sqlTable.ts
|
|
75295
75494
|
var import_knex = require("knex");
|
|
75296
75495
|
function isIgnoredType(type) {
|
|
75297
|
-
const ignored = ["link" /* LINK */, "formula" /* FORMULA */];
|
|
75496
|
+
const ignored = ["link" /* LINK */, "formula" /* FORMULA */, "ai" /* AI */];
|
|
75298
75497
|
return ignored.indexOf(type) !== -1;
|
|
75299
75498
|
}
|
|
75300
75499
|
function generateSchema(schema, table, tables, oldTable = null, renamed) {
|
|
@@ -75390,6 +75589,8 @@ function generateSchema(schema, table, tables, oldTable = null, renamed) {
|
|
|
75390
75589
|
break;
|
|
75391
75590
|
case "formula" /* FORMULA */:
|
|
75392
75591
|
break;
|
|
75592
|
+
case "ai" /* AI */:
|
|
75593
|
+
break;
|
|
75393
75594
|
case "attachment" /* ATTACHMENTS */:
|
|
75394
75595
|
case "attachment_single" /* ATTACHMENT_SINGLE */:
|
|
75395
75596
|
case "signature_single" /* SIGNATURE_SINGLE */:
|
|
@@ -75521,7 +75722,7 @@ var SqlTableQueryBuilder = class {
|
|
|
75521
75722
|
var sqlTable_default = SqlTableQueryBuilder;
|
|
75522
75723
|
|
|
75523
75724
|
// src/sql/sql.ts
|
|
75524
|
-
var
|
|
75725
|
+
var import_lodash5 = require("lodash");
|
|
75525
75726
|
var COUNT_FIELD_NAME = "__bb_total";
|
|
75526
75727
|
function getBaseLimit() {
|
|
75527
75728
|
const envLimit = environment_default.SQL_MAX_ROWS ? parseInt(environment_default.SQL_MAX_ROWS) : null;
|
|
@@ -75562,6 +75763,20 @@ function convertBooleans(query) {
|
|
|
75562
75763
|
function isSqs(table) {
|
|
75563
75764
|
return table.sourceType === "internal" /* INTERNAL */ || table.sourceId === INTERNAL_TABLE_SOURCE_ID;
|
|
75564
75765
|
}
|
|
75766
|
+
function escapeQuotes(value, quoteChar = '"') {
|
|
75767
|
+
return value.replace(new RegExp(quoteChar, "g"), `${quoteChar}${quoteChar}`);
|
|
75768
|
+
}
|
|
75769
|
+
function wrap(value, quoteChar = '"') {
|
|
75770
|
+
return `${quoteChar}${escapeQuotes(value, quoteChar)}${quoteChar}`;
|
|
75771
|
+
}
|
|
75772
|
+
function stringifyArray(value, quoteStyle = '"') {
|
|
75773
|
+
for (let i in value) {
|
|
75774
|
+
if (typeof value[i] === "string") {
|
|
75775
|
+
value[i] = wrap(value[i], quoteStyle);
|
|
75776
|
+
}
|
|
75777
|
+
}
|
|
75778
|
+
return `[${value.join(",")}]`;
|
|
75779
|
+
}
|
|
75565
75780
|
var allowEmptyRelationships = {
|
|
75566
75781
|
["equal" /* EQUAL */]: false,
|
|
75567
75782
|
["notEqual" /* NOT_EQUAL */]: true,
|
|
@@ -75599,28 +75814,24 @@ var InternalBuilder = class {
|
|
|
75599
75814
|
get table() {
|
|
75600
75815
|
return this.query.meta.table;
|
|
75601
75816
|
}
|
|
75817
|
+
get knexClient() {
|
|
75818
|
+
return this.knex.client;
|
|
75819
|
+
}
|
|
75602
75820
|
getFieldSchema(key) {
|
|
75603
75821
|
const { column } = this.splitter.run(key);
|
|
75604
75822
|
return this.table.schema[column];
|
|
75605
75823
|
}
|
|
75824
|
+
supportsILike() {
|
|
75825
|
+
return !(this.client === "oracledb" /* ORACLE */ || this.client === "sqlite3" /* SQL_LITE */);
|
|
75826
|
+
}
|
|
75606
75827
|
quoteChars() {
|
|
75607
|
-
|
|
75608
|
-
|
|
75609
|
-
case "pg" /* POSTGRES */:
|
|
75610
|
-
return ['"', '"'];
|
|
75611
|
-
case "mssql" /* MS_SQL */:
|
|
75612
|
-
return ["[", "]"];
|
|
75613
|
-
case "mariadb" /* MARIADB */:
|
|
75614
|
-
case "mysql2" /* MY_SQL */:
|
|
75615
|
-
case "sqlite3" /* SQL_LITE */:
|
|
75616
|
-
return ["`", "`"];
|
|
75617
|
-
}
|
|
75828
|
+
const wrapped = this.knexClient.wrapIdentifier("foo", {});
|
|
75829
|
+
return [wrapped[0], wrapped[wrapped.length - 1]];
|
|
75618
75830
|
}
|
|
75619
|
-
// Takes a string like foo and returns a quoted string like [foo] for SQL
|
|
75620
|
-
// and "foo" for Postgres.
|
|
75831
|
+
// Takes a string like foo and returns a quoted string like [foo] for SQL
|
|
75832
|
+
// Server and "foo" for Postgres.
|
|
75621
75833
|
quote(str) {
|
|
75622
|
-
|
|
75623
|
-
return `${start2}${str}${end2}`;
|
|
75834
|
+
return this.knexClient.wrapIdentifier(str, {});
|
|
75624
75835
|
}
|
|
75625
75836
|
isQuoted(key) {
|
|
75626
75837
|
const [start2, end2] = this.quoteChars();
|
|
@@ -75635,6 +75846,27 @@ var InternalBuilder = class {
|
|
|
75635
75846
|
}
|
|
75636
75847
|
return key.map((part) => this.quote(part)).join(".");
|
|
75637
75848
|
}
|
|
75849
|
+
quotedValue(value) {
|
|
75850
|
+
const formatter = this.knexClient.formatter(this.knexClient.queryBuilder());
|
|
75851
|
+
return formatter.wrap(value, false);
|
|
75852
|
+
}
|
|
75853
|
+
rawQuotedValue(value) {
|
|
75854
|
+
return this.knex.raw(this.quotedValue(value));
|
|
75855
|
+
}
|
|
75856
|
+
// Unfortuantely we cannot rely on knex's identifier escaping because it trims
|
|
75857
|
+
// the identifier string before escaping it, which breaks cases for us where
|
|
75858
|
+
// columns that start or end with a space aren't referenced correctly anymore.
|
|
75859
|
+
//
|
|
75860
|
+
// So whenever you're using an identifier binding in knex, e.g. knex.raw("??
|
|
75861
|
+
// as ?", ["foo", "bar"]), you need to make sure you call this:
|
|
75862
|
+
//
|
|
75863
|
+
// knex.raw("?? as ?", [this.quotedIdentifier("foo"), "bar"])
|
|
75864
|
+
//
|
|
75865
|
+
// Issue we filed against knex about this:
|
|
75866
|
+
// https://github.com/knex/knex/issues/6143
|
|
75867
|
+
rawQuotedIdentifier(key) {
|
|
75868
|
+
return this.knex.raw(this.quotedIdentifier(key));
|
|
75869
|
+
}
|
|
75638
75870
|
// Turns an identifier like a.b.c or `a`.`b`.`c` into ["a", "b", "c"]
|
|
75639
75871
|
splitIdentifier(key) {
|
|
75640
75872
|
const [start2, end2] = this.quoteChars();
|
|
@@ -75673,7 +75905,7 @@ var InternalBuilder = class {
|
|
|
75673
75905
|
const alias = this.getTableName(endpoint.entityId);
|
|
75674
75906
|
const schema = meta.table.schema;
|
|
75675
75907
|
if (!this.isFullSelectStatementRequired()) {
|
|
75676
|
-
return [this.knex.raw(`${
|
|
75908
|
+
return [this.knex.raw("??", [`${alias}.*`])];
|
|
75677
75909
|
}
|
|
75678
75910
|
return resource.fields.map((field) => {
|
|
75679
75911
|
const parts = field.split(/\./g);
|
|
@@ -75687,17 +75919,21 @@ var InternalBuilder = class {
|
|
|
75687
75919
|
}).filter(({ table }) => !table || table === alias).map(({ table, column, field }) => {
|
|
75688
75920
|
const columnSchema = schema[column];
|
|
75689
75921
|
if (this.SPECIAL_SELECT_CASES.POSTGRES_MONEY(columnSchema)) {
|
|
75690
|
-
return this.knex.raw(
|
|
75691
|
-
|
|
75692
|
-
|
|
75693
|
-
|
|
75694
|
-
);
|
|
75922
|
+
return this.knex.raw(`??::money::numeric as "${field}"`, [
|
|
75923
|
+
this.rawQuotedIdentifier([table, column].join(".")),
|
|
75924
|
+
field
|
|
75925
|
+
]);
|
|
75695
75926
|
}
|
|
75696
75927
|
if (this.SPECIAL_SELECT_CASES.MSSQL_DATES(columnSchema)) {
|
|
75697
|
-
return this.knex.raw(`CONVERT(varchar,
|
|
75928
|
+
return this.knex.raw(`CONVERT(varchar, ??, 108) as "${field}"`, [
|
|
75929
|
+
this.rawQuotedIdentifier(field)
|
|
75930
|
+
]);
|
|
75931
|
+
}
|
|
75932
|
+
if (table) {
|
|
75933
|
+
return this.rawQuotedIdentifier(`${table}.${column}`);
|
|
75934
|
+
} else {
|
|
75935
|
+
return this.rawQuotedIdentifier(field);
|
|
75698
75936
|
}
|
|
75699
|
-
const quoted = table ? `${this.quote(table)}.${this.quote(column)}` : this.quote(field);
|
|
75700
|
-
return this.knex.raw(quoted);
|
|
75701
75937
|
});
|
|
75702
75938
|
}
|
|
75703
75939
|
// OracleDB can't use character-large-objects (CLOBs) in WHERE clauses,
|
|
@@ -75712,12 +75948,15 @@ var InternalBuilder = class {
|
|
|
75712
75948
|
const parts = this.splitIdentifier(field);
|
|
75713
75949
|
const col = parts.pop();
|
|
75714
75950
|
const schema = this.table.schema[col];
|
|
75715
|
-
let identifier = this.
|
|
75951
|
+
let identifier = this.rawQuotedIdentifier(field);
|
|
75716
75952
|
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 */) {
|
|
75717
75953
|
if (opts?.forSelect) {
|
|
75718
|
-
identifier =
|
|
75954
|
+
identifier = this.knex.raw("to_char(??) as ??", [
|
|
75955
|
+
identifier,
|
|
75956
|
+
this.rawQuotedIdentifier(col)
|
|
75957
|
+
]);
|
|
75719
75958
|
} else {
|
|
75720
|
-
identifier =
|
|
75959
|
+
identifier = this.knex.raw("to_char(??)", [identifier]);
|
|
75721
75960
|
}
|
|
75722
75961
|
}
|
|
75723
75962
|
return identifier;
|
|
@@ -75762,7 +76001,7 @@ var InternalBuilder = class {
|
|
|
75762
76001
|
return body2;
|
|
75763
76002
|
}
|
|
75764
76003
|
parseFilters(filters) {
|
|
75765
|
-
filters = (0,
|
|
76004
|
+
filters = (0, import_lodash5.cloneDeep)(filters);
|
|
75766
76005
|
for (const op of Object.values(BasicOperator)) {
|
|
75767
76006
|
const filter = filters[op];
|
|
75768
76007
|
if (!filter) {
|
|
@@ -75822,7 +76061,6 @@ var InternalBuilder = class {
|
|
|
75822
76061
|
return query.andWhere(`${document}.fieldName`, "=", relationship.column);
|
|
75823
76062
|
}
|
|
75824
76063
|
addRelationshipForFilter(query, allowEmptyRelationships2, filterKey, whereCb) {
|
|
75825
|
-
const mainKnex = this.knex;
|
|
75826
76064
|
const { relationships, endpoint, tableAliases: aliases } = this.query;
|
|
75827
76065
|
const tableName = endpoint.entityId;
|
|
75828
76066
|
const fromAlias = aliases?.[tableName] || tableName;
|
|
@@ -75836,7 +76074,7 @@ var InternalBuilder = class {
|
|
|
75836
76074
|
const matchesTableName = matches2(relatedTableName) || matches2(toAlias);
|
|
75837
76075
|
const matchesRelationName = matches2(relationship.column);
|
|
75838
76076
|
if ((matchesTableName || matchesRelationName) && relationship.to && relationship.tableName) {
|
|
75839
|
-
const joinTable =
|
|
76077
|
+
const joinTable = this.knex.select(this.knex.raw(1)).from({ [toAlias]: relatedTableName });
|
|
75840
76078
|
let subQuery = joinTable.clone();
|
|
75841
76079
|
const manyToMany = validateManyToMany(relationship);
|
|
75842
76080
|
let updatedKey;
|
|
@@ -75863,9 +76101,7 @@ var InternalBuilder = class {
|
|
|
75863
76101
|
}).where(
|
|
75864
76102
|
`${throughAlias}.${manyToMany.from}`,
|
|
75865
76103
|
"=",
|
|
75866
|
-
|
|
75867
|
-
this.quotedIdentifier(`${fromAlias}.${manyToMany.fromPrimary}`)
|
|
75868
|
-
)
|
|
76104
|
+
this.rawQuotedIdentifier(`${fromAlias}.${manyToMany.fromPrimary}`)
|
|
75869
76105
|
);
|
|
75870
76106
|
if (this.client === "sqlite3" /* SQL_LITE */) {
|
|
75871
76107
|
subQuery = this.addJoinFieldCheck(subQuery, manyToMany);
|
|
@@ -75890,7 +76126,7 @@ var InternalBuilder = class {
|
|
|
75890
76126
|
subQuery = subQuery.where(
|
|
75891
76127
|
toKey,
|
|
75892
76128
|
"=",
|
|
75893
|
-
|
|
76129
|
+
this.rawQuotedIdentifier(foreignKey)
|
|
75894
76130
|
);
|
|
75895
76131
|
query = query.where((q2) => {
|
|
75896
76132
|
q2.whereExists(whereCb(updatedKey, subQuery.clone()));
|
|
@@ -75911,7 +76147,7 @@ var InternalBuilder = class {
|
|
|
75911
76147
|
const builder = this;
|
|
75912
76148
|
filters = this.parseFilters({ ...filters });
|
|
75913
76149
|
const aliases = this.query.tableAliases;
|
|
75914
|
-
const
|
|
76150
|
+
const shouldOr = filters.allOr;
|
|
75915
76151
|
const isSqlite = this.client === "sqlite3" /* SQL_LITE */;
|
|
75916
76152
|
const tableName = isSqlite ? this.table._id : this.table.name;
|
|
75917
76153
|
function getTableAlias(name) {
|
|
@@ -75950,7 +76186,7 @@ var InternalBuilder = class {
|
|
|
75950
76186
|
value
|
|
75951
76187
|
);
|
|
75952
76188
|
} else if (shouldProcessRelationship) {
|
|
75953
|
-
if (
|
|
76189
|
+
if (shouldOr) {
|
|
75954
76190
|
query = query.or;
|
|
75955
76191
|
}
|
|
75956
76192
|
query = builder.addRelationshipForFilter(
|
|
@@ -75965,75 +76201,89 @@ var InternalBuilder = class {
|
|
|
75965
76201
|
}
|
|
75966
76202
|
}
|
|
75967
76203
|
const like = (q2, key, value) => {
|
|
75968
|
-
|
|
75969
|
-
|
|
75970
|
-
|
|
75971
|
-
|
|
75972
|
-
|
|
75973
|
-
|
|
75974
|
-
return q2[rawFnc](`LOWER(${this.quotedIdentifier(key)}) LIKE ?`, [
|
|
76204
|
+
if (filters?.fuzzyOr || shouldOr) {
|
|
76205
|
+
q2 = q2.or;
|
|
76206
|
+
}
|
|
76207
|
+
if (this.client === "oracledb" /* ORACLE */ || this.client === "sqlite3" /* SQL_LITE */) {
|
|
76208
|
+
return q2.whereRaw(`LOWER(??) LIKE ?`, [
|
|
76209
|
+
this.rawQuotedIdentifier(key),
|
|
75975
76210
|
`%${value.toLowerCase()}%`
|
|
75976
76211
|
]);
|
|
75977
76212
|
}
|
|
76213
|
+
return q2.whereILike(
|
|
76214
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76215
|
+
this.rawQuotedIdentifier(key),
|
|
76216
|
+
this.knex.raw("?", [`%${value}%`])
|
|
76217
|
+
);
|
|
75978
76218
|
};
|
|
75979
76219
|
const contains = (mode, any = false) => {
|
|
75980
|
-
|
|
75981
|
-
|
|
75982
|
-
|
|
75983
|
-
for (let i in value) {
|
|
75984
|
-
if (typeof value[i] === "string") {
|
|
75985
|
-
value[i] = `${quoteStyle}${value[i]}${quoteStyle}`;
|
|
75986
|
-
}
|
|
76220
|
+
function addModifiers(q2) {
|
|
76221
|
+
if (shouldOr || mode === filters?.containsAny) {
|
|
76222
|
+
q2 = q2.or;
|
|
75987
76223
|
}
|
|
75988
|
-
|
|
76224
|
+
if (mode === filters?.notContains) {
|
|
76225
|
+
q2 = q2.not;
|
|
76226
|
+
}
|
|
76227
|
+
return q2;
|
|
75989
76228
|
}
|
|
75990
76229
|
if (this.client === "pg" /* POSTGRES */) {
|
|
75991
76230
|
iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
|
|
75992
|
-
|
|
75993
|
-
|
|
75994
|
-
|
|
75995
|
-
|
|
75996
|
-
|
|
75997
|
-
|
|
75998
|
-
|
|
75999
|
-
|
|
76000
|
-
|
|
76001
|
-
|
|
76002
|
-
|
|
76231
|
+
q2 = addModifiers(q2);
|
|
76232
|
+
if (any) {
|
|
76233
|
+
return q2.whereRaw(`COALESCE(??::jsonb \\?| array??, FALSE)`, [
|
|
76234
|
+
this.rawQuotedIdentifier(key),
|
|
76235
|
+
this.knex.raw(stringifyArray(value, "'"))
|
|
76236
|
+
]);
|
|
76237
|
+
} else {
|
|
76238
|
+
return q2.whereRaw(`COALESCE(??::jsonb @> '??', FALSE)`, [
|
|
76239
|
+
this.rawQuotedIdentifier(key),
|
|
76240
|
+
this.knex.raw(stringifyArray(value))
|
|
76241
|
+
]);
|
|
76242
|
+
}
|
|
76003
76243
|
});
|
|
76004
76244
|
} else if (this.client === "mysql2" /* MY_SQL */ || this.client === "mariadb" /* MARIADB */) {
|
|
76005
|
-
const jsonFnc = any ? "JSON_OVERLAPS" : "JSON_CONTAINS";
|
|
76006
76245
|
iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
|
|
76007
|
-
return q2[
|
|
76008
|
-
|
|
76009
|
-
|
|
76010
|
-
)
|
|
76011
|
-
);
|
|
76246
|
+
return addModifiers(q2).whereRaw(`COALESCE(?(??, ?), FALSE)`, [
|
|
76247
|
+
this.knex.raw(any ? "JSON_OVERLAPS" : "JSON_CONTAINS"),
|
|
76248
|
+
this.rawQuotedIdentifier(key),
|
|
76249
|
+
this.knex.raw(wrap(stringifyArray(value)))
|
|
76250
|
+
]);
|
|
76012
76251
|
});
|
|
76013
76252
|
} else {
|
|
76014
|
-
const andOr = mode === filters?.containsAny ? " OR " : " AND ";
|
|
76015
76253
|
iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
|
|
76016
|
-
|
|
76017
|
-
const identifier = this.quotedIdentifier(key);
|
|
76018
|
-
for (let i in value) {
|
|
76019
|
-
if (typeof value[i] === "string") {
|
|
76020
|
-
value[i] = `%"${value[i].toLowerCase()}"%`;
|
|
76021
|
-
} else {
|
|
76022
|
-
value[i] = `%${value[i]}%`;
|
|
76023
|
-
}
|
|
76024
|
-
statement += `${statement ? andOr : ""}COALESCE(LOWER(${identifier}), '') LIKE ?`;
|
|
76025
|
-
}
|
|
76026
|
-
if (statement === "") {
|
|
76254
|
+
if (value.length === 0) {
|
|
76027
76255
|
return q2;
|
|
76028
76256
|
}
|
|
76029
|
-
|
|
76030
|
-
|
|
76031
|
-
|
|
76032
|
-
|
|
76033
|
-
)
|
|
76034
|
-
|
|
76035
|
-
|
|
76036
|
-
|
|
76257
|
+
q2 = q2.where((subQuery) => {
|
|
76258
|
+
if (mode === filters?.notContains) {
|
|
76259
|
+
subQuery = subQuery.not;
|
|
76260
|
+
}
|
|
76261
|
+
subQuery = subQuery.where((subSubQuery) => {
|
|
76262
|
+
for (const elem of value) {
|
|
76263
|
+
if (mode === filters?.containsAny) {
|
|
76264
|
+
subSubQuery = subSubQuery.or;
|
|
76265
|
+
} else {
|
|
76266
|
+
subSubQuery = subSubQuery.and;
|
|
76267
|
+
}
|
|
76268
|
+
const lower = typeof elem === "string" ? `"${elem.toLowerCase()}"` : elem;
|
|
76269
|
+
subSubQuery = subSubQuery.whereLike(
|
|
76270
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76271
|
+
this.knex.raw(`COALESCE(LOWER(??), '')`, [
|
|
76272
|
+
this.rawQuotedIdentifier(key)
|
|
76273
|
+
]),
|
|
76274
|
+
`%${lower}%`
|
|
76275
|
+
);
|
|
76276
|
+
}
|
|
76277
|
+
});
|
|
76278
|
+
if (mode === filters?.notContains) {
|
|
76279
|
+
subQuery = subQuery.or.whereNull(
|
|
76280
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76281
|
+
this.rawQuotedIdentifier(key)
|
|
76282
|
+
);
|
|
76283
|
+
}
|
|
76284
|
+
return subQuery;
|
|
76285
|
+
});
|
|
76286
|
+
return q2;
|
|
76037
76287
|
});
|
|
76038
76288
|
}
|
|
76039
76289
|
};
|
|
@@ -76056,41 +76306,41 @@ var InternalBuilder = class {
|
|
|
76056
76306
|
});
|
|
76057
76307
|
}
|
|
76058
76308
|
if (filters.oneOf) {
|
|
76059
|
-
const fnc = allOr ? "orWhereIn" : "whereIn";
|
|
76060
76309
|
iterate(
|
|
76061
76310
|
filters.oneOf,
|
|
76062
76311
|
"oneOf" /* ONE_OF */,
|
|
76063
76312
|
(q2, key, array) => {
|
|
76313
|
+
if (shouldOr) {
|
|
76314
|
+
q2 = q2.or;
|
|
76315
|
+
}
|
|
76064
76316
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76065
76317
|
key = this.convertClobs(key);
|
|
76066
|
-
array = Array.isArray(array) ? array : [array];
|
|
76067
|
-
const binding = new Array(array.length).fill("?").join(",");
|
|
76068
|
-
return q2.whereRaw(`${key} IN (${binding})`, array);
|
|
76069
|
-
} else {
|
|
76070
|
-
return q2[fnc](key, Array.isArray(array) ? array : [array]);
|
|
76071
76318
|
}
|
|
76319
|
+
return q2.whereIn(key, Array.isArray(array) ? array : [array]);
|
|
76072
76320
|
},
|
|
76073
76321
|
(q2, key, array) => {
|
|
76322
|
+
if (shouldOr) {
|
|
76323
|
+
q2 = q2.or;
|
|
76324
|
+
}
|
|
76074
76325
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76075
|
-
|
|
76076
|
-
const binding = `(${array.map((a) => `(${new Array(a.length).fill("?").join(",")})`).join(",")})`;
|
|
76077
|
-
return q2.whereRaw(`${keyStr} IN ${binding}`, array.flat());
|
|
76078
|
-
} else {
|
|
76079
|
-
return q2[fnc](key, Array.isArray(array) ? array : [array]);
|
|
76326
|
+
key = key.map((k) => this.convertClobs(k));
|
|
76080
76327
|
}
|
|
76328
|
+
return q2.whereIn(key, Array.isArray(array) ? array : [array]);
|
|
76081
76329
|
}
|
|
76082
76330
|
);
|
|
76083
76331
|
}
|
|
76084
76332
|
if (filters.string) {
|
|
76085
76333
|
iterate(filters.string, "string" /* STRING */, (q2, key, value) => {
|
|
76086
|
-
|
|
76087
|
-
|
|
76088
|
-
|
|
76089
|
-
|
|
76090
|
-
|
|
76091
|
-
|
|
76334
|
+
if (shouldOr) {
|
|
76335
|
+
q2 = q2.or;
|
|
76336
|
+
}
|
|
76337
|
+
if (this.client === "oracledb" /* ORACLE */ || this.client === "sqlite3" /* SQL_LITE */) {
|
|
76338
|
+
return q2.whereRaw(`LOWER(??) LIKE ?`, [
|
|
76339
|
+
this.rawQuotedIdentifier(key),
|
|
76092
76340
|
`${value.toLowerCase()}%`
|
|
76093
76341
|
]);
|
|
76342
|
+
} else {
|
|
76343
|
+
return q2.whereILike(key, `${value}%`);
|
|
76094
76344
|
}
|
|
76095
76345
|
});
|
|
76096
76346
|
}
|
|
@@ -76110,56 +76360,52 @@ var InternalBuilder = class {
|
|
|
76110
76360
|
}
|
|
76111
76361
|
const lowValid = isValidFilter(value.low), highValid = isValidFilter(value.high);
|
|
76112
76362
|
const schema = this.getFieldSchema(key);
|
|
76363
|
+
let rawKey = key;
|
|
76364
|
+
let high = value.high;
|
|
76365
|
+
let low = value.low;
|
|
76113
76366
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76114
|
-
|
|
76367
|
+
rawKey = this.convertClobs(key);
|
|
76368
|
+
} else if (this.client === "sqlite3" /* SQL_LITE */ && schema?.type === "bigint" /* BIGINT */) {
|
|
76369
|
+
rawKey = this.knex.raw("CAST(?? AS INTEGER)", [
|
|
76370
|
+
this.rawQuotedIdentifier(key)
|
|
76371
|
+
]);
|
|
76372
|
+
high = this.knex.raw("CAST(? AS INTEGER)", [value.high]);
|
|
76373
|
+
low = this.knex.raw("CAST(? AS INTEGER)", [value.low]);
|
|
76374
|
+
}
|
|
76375
|
+
if (shouldOr) {
|
|
76376
|
+
q2 = q2.or;
|
|
76115
76377
|
}
|
|
76116
76378
|
if (lowValid && highValid) {
|
|
76117
|
-
|
|
76118
|
-
return q2.whereRaw(
|
|
76119
|
-
`CAST(${key} AS INTEGER) BETWEEN CAST(? AS INTEGER) AND CAST(? AS INTEGER)`,
|
|
76120
|
-
[value.low, value.high]
|
|
76121
|
-
);
|
|
76122
|
-
} else {
|
|
76123
|
-
const fnc = allOr ? "orWhereBetween" : "whereBetween";
|
|
76124
|
-
return q2[fnc](key, [value.low, value.high]);
|
|
76125
|
-
}
|
|
76379
|
+
return q2.whereBetween(rawKey, [low, high]);
|
|
76126
76380
|
} else if (lowValid) {
|
|
76127
|
-
|
|
76128
|
-
return q2.whereRaw(`CAST(${key} AS INTEGER) >= CAST(? AS INTEGER)`, [
|
|
76129
|
-
value.low
|
|
76130
|
-
]);
|
|
76131
|
-
} else {
|
|
76132
|
-
const fnc = allOr ? "orWhere" : "where";
|
|
76133
|
-
return q2[fnc](key, ">=", value.low);
|
|
76134
|
-
}
|
|
76381
|
+
return q2.where(rawKey, ">=", low);
|
|
76135
76382
|
} else if (highValid) {
|
|
76136
|
-
|
|
76137
|
-
return q2.whereRaw(`CAST(${key} AS INTEGER) <= CAST(? AS INTEGER)`, [
|
|
76138
|
-
value.high
|
|
76139
|
-
]);
|
|
76140
|
-
} else {
|
|
76141
|
-
const fnc = allOr ? "orWhere" : "where";
|
|
76142
|
-
return q2[fnc](key, "<=", value.high);
|
|
76143
|
-
}
|
|
76383
|
+
return q2.where(rawKey, "<=", high);
|
|
76144
76384
|
}
|
|
76145
76385
|
return q2;
|
|
76146
76386
|
});
|
|
76147
76387
|
}
|
|
76148
76388
|
if (filters.equal) {
|
|
76149
76389
|
iterate(filters.equal, "equal" /* EQUAL */, (q2, key, value) => {
|
|
76150
|
-
|
|
76390
|
+
if (shouldOr) {
|
|
76391
|
+
q2 = q2.or;
|
|
76392
|
+
}
|
|
76151
76393
|
if (this.client === "mssql" /* MS_SQL */) {
|
|
76152
|
-
return q2[
|
|
76153
|
-
|
|
76154
|
-
[value]
|
|
76155
|
-
);
|
|
76156
|
-
} else if (this.client === "oracledb" /* ORACLE */) {
|
|
76157
|
-
const identifier = this.convertClobs(key);
|
|
76158
|
-
return q2[fnc](`(${identifier} IS NOT NULL AND ${identifier} = ?)`, [
|
|
76394
|
+
return q2.whereRaw(`CASE WHEN ?? = ? THEN 1 ELSE 0 END = 1`, [
|
|
76395
|
+
this.rawQuotedIdentifier(key),
|
|
76159
76396
|
value
|
|
76160
76397
|
]);
|
|
76398
|
+
} else if (this.client === "oracledb" /* ORACLE */) {
|
|
76399
|
+
const identifier = this.convertClobs(key);
|
|
76400
|
+
return q2.where(
|
|
76401
|
+
(subq) => (
|
|
76402
|
+
// @ts-expect-error knex types are wrong, raw is fine here
|
|
76403
|
+
subq.whereNotNull(identifier).andWhere(identifier, value)
|
|
76404
|
+
)
|
|
76405
|
+
);
|
|
76161
76406
|
} else {
|
|
76162
|
-
return q2
|
|
76407
|
+
return q2.whereRaw(`COALESCE(?? = ?, FALSE)`, [
|
|
76408
|
+
this.rawQuotedIdentifier(key),
|
|
76163
76409
|
value
|
|
76164
76410
|
]);
|
|
76165
76411
|
}
|
|
@@ -76167,20 +76413,22 @@ var InternalBuilder = class {
|
|
|
76167
76413
|
}
|
|
76168
76414
|
if (filters.notEqual) {
|
|
76169
76415
|
iterate(filters.notEqual, "notEqual" /* NOT_EQUAL */, (q2, key, value) => {
|
|
76170
|
-
|
|
76416
|
+
if (shouldOr) {
|
|
76417
|
+
q2 = q2.or;
|
|
76418
|
+
}
|
|
76171
76419
|
if (this.client === "mssql" /* MS_SQL */) {
|
|
76172
|
-
return q2[
|
|
76173
|
-
|
|
76174
|
-
|
|
76175
|
-
);
|
|
76420
|
+
return q2.whereRaw(`CASE WHEN ?? = ? THEN 1 ELSE 0 END = 0`, [
|
|
76421
|
+
this.rawQuotedIdentifier(key),
|
|
76422
|
+
value
|
|
76423
|
+
]);
|
|
76176
76424
|
} else if (this.client === "oracledb" /* ORACLE */) {
|
|
76177
76425
|
const identifier = this.convertClobs(key);
|
|
76178
|
-
return q2
|
|
76179
|
-
|
|
76180
|
-
|
|
76181
|
-
);
|
|
76426
|
+
return q2.where(
|
|
76427
|
+
(subq) => subq.not.whereNull(identifier).and.where(identifier, "!=", value)
|
|
76428
|
+
).or.whereNull(identifier);
|
|
76182
76429
|
} else {
|
|
76183
|
-
return q2
|
|
76430
|
+
return q2.whereRaw(`COALESCE(?? != ?, TRUE)`, [
|
|
76431
|
+
this.rawQuotedIdentifier(key),
|
|
76184
76432
|
value
|
|
76185
76433
|
]);
|
|
76186
76434
|
}
|
|
@@ -76188,14 +76436,18 @@ var InternalBuilder = class {
|
|
|
76188
76436
|
}
|
|
76189
76437
|
if (filters.empty) {
|
|
76190
76438
|
iterate(filters.empty, "empty" /* EMPTY */, (q2, key) => {
|
|
76191
|
-
|
|
76192
|
-
|
|
76439
|
+
if (shouldOr) {
|
|
76440
|
+
q2 = q2.or;
|
|
76441
|
+
}
|
|
76442
|
+
return q2.whereNull(key);
|
|
76193
76443
|
});
|
|
76194
76444
|
}
|
|
76195
76445
|
if (filters.notEmpty) {
|
|
76196
76446
|
iterate(filters.notEmpty, "notEmpty" /* NOT_EMPTY */, (q2, key) => {
|
|
76197
|
-
|
|
76198
|
-
|
|
76447
|
+
if (shouldOr) {
|
|
76448
|
+
q2 = q2.or;
|
|
76449
|
+
}
|
|
76450
|
+
return q2.whereNotNull(key);
|
|
76199
76451
|
});
|
|
76200
76452
|
}
|
|
76201
76453
|
if (filters.contains) {
|
|
@@ -76264,7 +76516,7 @@ var InternalBuilder = class {
|
|
|
76264
76516
|
const selectFields = qualifiedFields.map(
|
|
76265
76517
|
(field) => this.convertClobs(field, { forSelect: true })
|
|
76266
76518
|
);
|
|
76267
|
-
query = query.
|
|
76519
|
+
query = query.groupBy(groupByFields).select(selectFields);
|
|
76268
76520
|
} else {
|
|
76269
76521
|
query = query.groupBy(qualifiedFields).select(qualifiedFields);
|
|
76270
76522
|
}
|
|
@@ -76276,11 +76528,10 @@ var InternalBuilder = class {
|
|
|
76276
76528
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76277
76529
|
const field = this.convertClobs(`${tableName}.${aggregation.field}`);
|
|
76278
76530
|
query = query.select(
|
|
76279
|
-
this.knex.raw(
|
|
76280
|
-
|
|
76281
|
-
|
|
76282
|
-
|
|
76283
|
-
)
|
|
76531
|
+
this.knex.raw(`COUNT(DISTINCT ??) as ??`, [
|
|
76532
|
+
field,
|
|
76533
|
+
aggregation.name
|
|
76534
|
+
])
|
|
76284
76535
|
);
|
|
76285
76536
|
} else {
|
|
76286
76537
|
query = query.countDistinct(
|
|
@@ -76335,9 +76586,11 @@ var InternalBuilder = class {
|
|
|
76335
76586
|
} else {
|
|
76336
76587
|
let composite = `${aliased}.${key}`;
|
|
76337
76588
|
if (this.client === "oracledb" /* ORACLE */) {
|
|
76338
|
-
query = query.orderByRaw(
|
|
76339
|
-
|
|
76340
|
-
|
|
76589
|
+
query = query.orderByRaw(`?? ?? nulls ??`, [
|
|
76590
|
+
this.convertClobs(composite),
|
|
76591
|
+
this.knex.raw(direction),
|
|
76592
|
+
this.knex.raw(nulls)
|
|
76593
|
+
]);
|
|
76341
76594
|
} else {
|
|
76342
76595
|
query = query.orderBy(composite, direction, nulls);
|
|
76343
76596
|
}
|
|
@@ -76359,17 +76612,18 @@ var InternalBuilder = class {
|
|
|
76359
76612
|
}
|
|
76360
76613
|
buildJsonField(field) {
|
|
76361
76614
|
const parts = field.split(".");
|
|
76362
|
-
let
|
|
76615
|
+
let unaliased;
|
|
76616
|
+
let tableField;
|
|
76363
76617
|
if (parts.length > 1) {
|
|
76364
76618
|
const alias = parts.shift();
|
|
76365
76619
|
unaliased = parts.join(".");
|
|
76366
|
-
tableField = `${
|
|
76620
|
+
tableField = `${alias}.${unaliased}`;
|
|
76367
76621
|
} else {
|
|
76368
76622
|
unaliased = parts.join(".");
|
|
76369
|
-
tableField =
|
|
76623
|
+
tableField = unaliased;
|
|
76370
76624
|
}
|
|
76371
76625
|
const separator = this.client === "oracledb" /* ORACLE */ ? " VALUE " : ",";
|
|
76372
|
-
return
|
|
76626
|
+
return this.knex.raw(`?${separator}??`, [unaliased, this.rawQuotedIdentifier(tableField)]).toString();
|
|
76373
76627
|
}
|
|
76374
76628
|
maxFunctionParameters() {
|
|
76375
76629
|
switch (this.client) {
|
|
@@ -76433,11 +76687,11 @@ var InternalBuilder = class {
|
|
|
76433
76687
|
subQuery = subQuery.where(
|
|
76434
76688
|
correlatedTo,
|
|
76435
76689
|
"=",
|
|
76436
|
-
|
|
76690
|
+
this.rawQuotedIdentifier(correlatedFrom)
|
|
76437
76691
|
);
|
|
76438
76692
|
const standardWrap = (select) => {
|
|
76439
76693
|
subQuery = subQuery.select(`${toAlias}.*`).limit(getRelationshipLimit());
|
|
76440
|
-
return knex3.select(
|
|
76694
|
+
return knex3.select(select).from({
|
|
76441
76695
|
[toAlias]: subQuery
|
|
76442
76696
|
});
|
|
76443
76697
|
};
|
|
@@ -76446,12 +76700,12 @@ var InternalBuilder = class {
|
|
|
76446
76700
|
case "sqlite3" /* SQL_LITE */:
|
|
76447
76701
|
subQuery = this.addJoinFieldCheck(subQuery, relationship);
|
|
76448
76702
|
wrapperQuery = standardWrap(
|
|
76449
|
-
`json_group_array(json_object(${fieldList}))`
|
|
76703
|
+
this.knex.raw(`json_group_array(json_object(${fieldList}))`)
|
|
76450
76704
|
);
|
|
76451
76705
|
break;
|
|
76452
76706
|
case "pg" /* POSTGRES */:
|
|
76453
76707
|
wrapperQuery = standardWrap(
|
|
76454
|
-
`json_agg(json_build_object(${fieldList}))`
|
|
76708
|
+
this.knex.raw(`json_agg(json_build_object(${fieldList}))`)
|
|
76455
76709
|
);
|
|
76456
76710
|
break;
|
|
76457
76711
|
case "mariadb" /* MARIADB */:
|
|
@@ -76464,16 +76718,19 @@ var InternalBuilder = class {
|
|
|
76464
76718
|
case "mysql2" /* MY_SQL */:
|
|
76465
76719
|
case "oracledb" /* ORACLE */:
|
|
76466
76720
|
wrapperQuery = standardWrap(
|
|
76467
|
-
`json_arrayagg(json_object(${fieldList}))`
|
|
76721
|
+
this.knex.raw(`json_arrayagg(json_object(${fieldList}))`)
|
|
76468
76722
|
);
|
|
76469
76723
|
break;
|
|
76470
|
-
case "mssql" /* MS_SQL */:
|
|
76724
|
+
case "mssql" /* MS_SQL */: {
|
|
76725
|
+
const comparatorQuery = knex3.select(`${fromAlias}.*`).from({
|
|
76726
|
+
[fromAlias]: subQuery.select(`${toAlias}.*`).limit(getRelationshipLimit())
|
|
76727
|
+
});
|
|
76471
76728
|
wrapperQuery = knex3.raw(
|
|
76472
|
-
`(SELECT
|
|
76473
|
-
|
|
76474
|
-
})} FOR JSON PATH))`
|
|
76729
|
+
`(SELECT ?? = (${comparatorQuery} FOR JSON PATH))`,
|
|
76730
|
+
[this.rawQuotedIdentifier(toAlias)]
|
|
76475
76731
|
);
|
|
76476
76732
|
break;
|
|
76733
|
+
}
|
|
76477
76734
|
default:
|
|
76478
76735
|
throw new Error(`JSON relationships not implement for ${sqlClient}`);
|
|
76479
76736
|
}
|