@objectstack/core 11.0.0 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +55 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -2
- package/dist/index.d.ts +32 -2
- package/dist/index.js +53 -10
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -66,12 +66,14 @@ __export(index_exports, {
|
|
|
66
66
|
createMemoryQueue: () => createMemoryQueue,
|
|
67
67
|
createPluginConfigValidator: () => createPluginConfigValidator,
|
|
68
68
|
createPluginPermissionEnforcer: () => createPluginPermissionEnforcer,
|
|
69
|
+
evaluateAuthGate: () => evaluateAuthGate,
|
|
69
70
|
extractApiKey: () => extractApiKey,
|
|
70
71
|
generateApiKey: () => generateApiKey,
|
|
71
72
|
generateEd25519KeyPair: () => generateEd25519KeyPair,
|
|
72
73
|
getEnv: () => getEnv,
|
|
73
74
|
getMemoryUsage: () => getMemoryUsage,
|
|
74
75
|
hashApiKey: () => hashApiKey,
|
|
76
|
+
isAuthGateAllowlisted: () => isAuthGateAllowlisted,
|
|
75
77
|
isExpired: () => isExpired,
|
|
76
78
|
isNode: () => isNode,
|
|
77
79
|
parseScopes: () => parseScopes,
|
|
@@ -4126,9 +4128,19 @@ async function resolveAuthzContext(input) {
|
|
|
4126
4128
|
ctx.userId = userId;
|
|
4127
4129
|
if (tenantId) ctx.tenantId = tenantId;
|
|
4128
4130
|
if (!ql || typeof ql.find !== "function") return ctx;
|
|
4131
|
+
let userRowLoaded = false;
|
|
4132
|
+
let userRow;
|
|
4133
|
+
const getUserRow = async () => {
|
|
4134
|
+
if (!userRowLoaded) {
|
|
4135
|
+
userRowLoaded = true;
|
|
4136
|
+
const rows = await tryFind(ql, "sys_user", { id: userId }, 1);
|
|
4137
|
+
userRow = rows[0];
|
|
4138
|
+
}
|
|
4139
|
+
return userRow;
|
|
4140
|
+
};
|
|
4129
4141
|
if (!ctx.email) {
|
|
4130
|
-
const
|
|
4131
|
-
if (
|
|
4142
|
+
const u = await getUserRow();
|
|
4143
|
+
if (u?.email) ctx.email = String(u.email);
|
|
4132
4144
|
}
|
|
4133
4145
|
const memberWhere = tenantId ? { user_id: userId, organization_id: tenantId } : { user_id: userId };
|
|
4134
4146
|
const members = await tryFind(ql, "sys_member", memberWhere, 50);
|
|
@@ -4209,8 +4221,7 @@ async function resolveAuthzContext(input) {
|
|
|
4209
4221
|
ctx.roles.unshift(import_spec.BUILTIN_ROLE_PLATFORM_ADMIN);
|
|
4210
4222
|
}
|
|
4211
4223
|
if (!ctx.permissions.includes("ai_seat")) {
|
|
4212
|
-
const
|
|
4213
|
-
const aiAccess = seatRows?.[0]?.ai_access;
|
|
4224
|
+
const aiAccess = (await getUserRow())?.ai_access;
|
|
4214
4225
|
if (aiAccess === true || aiAccess === 1 || aiAccess === "1") ctx.permissions.push("ai_seat");
|
|
4215
4226
|
}
|
|
4216
4227
|
return ctx;
|
|
@@ -4252,13 +4263,45 @@ async function resolveLocalizationContext(input) {
|
|
|
4252
4263
|
}
|
|
4253
4264
|
} catch {
|
|
4254
4265
|
}
|
|
4255
|
-
const
|
|
4256
|
-
|
|
4257
|
-
|
|
4266
|
+
const rows = await tryFind(
|
|
4267
|
+
ql,
|
|
4268
|
+
"sys_setting",
|
|
4269
|
+
{ namespace: "localization", key: { $in: ["timezone", "locale", "currency"] }, scope: "tenant" },
|
|
4270
|
+
10
|
|
4271
|
+
);
|
|
4272
|
+
const valueOf = (k) => rows.find((r) => r.key === k)?.value;
|
|
4273
|
+
return {
|
|
4274
|
+
timezone: coerceTimeZone(valueOf("timezone")) ?? "UTC",
|
|
4275
|
+
locale: coerceLocale(valueOf("locale")) ?? "en-US",
|
|
4276
|
+
currency: coerceCurrency(valueOf("currency"))
|
|
4277
|
+
};
|
|
4278
|
+
}
|
|
4279
|
+
|
|
4280
|
+
// src/security/auth-gate.ts
|
|
4281
|
+
var ALLOW_PREFIXES = ["/api/v1/auth/", "/api/auth/", "/auth/"];
|
|
4282
|
+
var ALLOW_SUFFIXES = ["/health", "/ready", "/discovery", "/me/apps", "/me/localization"];
|
|
4283
|
+
function isAuthGateAllowlisted(rawPath) {
|
|
4284
|
+
if (!rawPath) return true;
|
|
4285
|
+
let path = rawPath.split("?")[0] || "/";
|
|
4286
|
+
let end = path.length;
|
|
4287
|
+
while (end > 1 && path.charCodeAt(end - 1) === 47) end--;
|
|
4288
|
+
path = path.slice(0, end) || "/";
|
|
4289
|
+
if (path.includes("/auth/")) return true;
|
|
4290
|
+
for (const p of ALLOW_PREFIXES) {
|
|
4291
|
+
if (path.startsWith(p) || path === p.replace(/\/$/, "")) return true;
|
|
4292
|
+
}
|
|
4293
|
+
for (const s of ALLOW_SUFFIXES) {
|
|
4294
|
+
if (path.endsWith(s)) return true;
|
|
4295
|
+
}
|
|
4296
|
+
return false;
|
|
4297
|
+
}
|
|
4298
|
+
function evaluateAuthGate(sessionUser, path) {
|
|
4299
|
+
const gate = sessionUser?.authGate;
|
|
4300
|
+
if (!gate || typeof gate.code !== "string") return null;
|
|
4301
|
+
if (isAuthGateAllowlisted(path)) return null;
|
|
4258
4302
|
return {
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
currency: coerceCurrency(currencyRows[0]?.value)
|
|
4303
|
+
code: gate.code,
|
|
4304
|
+
message: typeof gate.message === "string" && gate.message ? gate.message : "Access is blocked by an authentication policy."
|
|
4262
4305
|
};
|
|
4263
4306
|
}
|
|
4264
4307
|
|
|
@@ -5238,12 +5281,14 @@ var NamespaceResolver = class {
|
|
|
5238
5281
|
createMemoryQueue,
|
|
5239
5282
|
createPluginConfigValidator,
|
|
5240
5283
|
createPluginPermissionEnforcer,
|
|
5284
|
+
evaluateAuthGate,
|
|
5241
5285
|
extractApiKey,
|
|
5242
5286
|
generateApiKey,
|
|
5243
5287
|
generateEd25519KeyPair,
|
|
5244
5288
|
getEnv,
|
|
5245
5289
|
getMemoryUsage,
|
|
5246
5290
|
hashApiKey,
|
|
5291
|
+
isAuthGateAllowlisted,
|
|
5247
5292
|
isExpired,
|
|
5248
5293
|
isNode,
|
|
5249
5294
|
parseScopes,
|