@objectstack/core 14.3.0 → 14.5.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 CHANGED
@@ -78,6 +78,8 @@ __export(index_exports, {
78
78
  hashApiKey: () => hashApiKey,
79
79
  isAuthGateAllowlisted: () => isAuthGateAllowlisted,
80
80
  isExpired: () => isExpired,
81
+ isGrantActive: () => isGrantActive,
82
+ isGrantExpired: () => isGrantExpired,
81
83
  isNode: () => isNode,
82
84
  parseScopes: () => parseScopes,
83
85
  parseSignature: () => parseSignature,
@@ -4215,6 +4217,33 @@ function safeJsonParse(s, fallback) {
4215
4217
 
4216
4218
  // src/security/resolve-authz-context.ts
4217
4219
  var import_spec = require("@objectstack/spec");
4220
+
4221
+ // src/security/grant-validity.ts
4222
+ function toEpochMs(value) {
4223
+ if (value == null || value === "") return void 0;
4224
+ if (typeof value === "number") {
4225
+ return value < 1e12 ? value * 1e3 : value;
4226
+ }
4227
+ if (value instanceof Date) return value.getTime();
4228
+ if (typeof value === "string") return Date.parse(value);
4229
+ return Number.NaN;
4230
+ }
4231
+ function isGrantActive(row, nowMs) {
4232
+ if (!row) return false;
4233
+ const from = toEpochMs(row.valid_from ?? row.validFrom);
4234
+ if (from !== void 0 && !(nowMs >= from)) return false;
4235
+ const until = toEpochMs(row.valid_until ?? row.validUntil);
4236
+ if (until !== void 0 && !(nowMs < until)) return false;
4237
+ return true;
4238
+ }
4239
+ function isGrantExpired(row, nowMs) {
4240
+ if (!row) return false;
4241
+ const until = toEpochMs(row.valid_until ?? row.validUntil);
4242
+ if (until === void 0) return false;
4243
+ return !(nowMs < until);
4244
+ }
4245
+
4246
+ // src/security/resolve-authz-context.ts
4218
4247
  function safeJsonParse2(s, fallback) {
4219
4248
  try {
4220
4249
  return JSON.parse(s);
@@ -4288,10 +4317,12 @@ async function resolveAuthzContext(input) {
4288
4317
  }
4289
4318
  }
4290
4319
  }
4320
+ const nowMs = input.nowMs ?? Date.now();
4291
4321
  const userPositionRows = await tryFind(ql, "sys_user_position", { user_id: userId }, 200);
4292
4322
  for (const ur of userPositionRows) {
4293
4323
  const org = ur.organization_id ?? null;
4294
4324
  if (org && tenantId && org !== tenantId) continue;
4325
+ if (!isGrantActive(ur, nowMs)) continue;
4295
4326
  const r = ur.position;
4296
4327
  if (typeof r === "string" && r && !ctx.positions.includes(r)) ctx.positions.push(r);
4297
4328
  }
@@ -4305,7 +4336,8 @@ async function resolveAuthzContext(input) {
4305
4336
  } else {
4306
4337
  ctx.org_user_ids = [userId];
4307
4338
  }
4308
- const upsRows = await tryFind(ql, "sys_user_permission_set", { user_id: userId }, 100);
4339
+ const upsRowsAll = await tryFind(ql, "sys_user_permission_set", { user_id: userId }, 100);
4340
+ const upsRows = upsRowsAll.filter((r) => isGrantActive(r, nowMs));
4309
4341
  const psIds = new Set(
4310
4342
  upsRows.filter((r) => {
4311
4343
  const org = r.organization_id ?? r.organizationId ?? null;
@@ -5511,6 +5543,8 @@ var NamespaceResolver = class {
5511
5543
  hashApiKey,
5512
5544
  isAuthGateAllowlisted,
5513
5545
  isExpired,
5546
+ isGrantActive,
5547
+ isGrantExpired,
5514
5548
  isNode,
5515
5549
  parseScopes,
5516
5550
  parseSignature,