@objectstack/plugin-sharing 9.10.0 → 9.11.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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +43 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +122 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/objects/sys-sharing-rule.object.ts +2 -2
- package/src/role-graph.test.ts +60 -0
- package/src/role-graph.ts +108 -0
- package/src/sharing-rule-service.ts +11 -0
- package/src/sharing-service.test.ts +36 -0
- package/src/sharing-service.ts +11 -5
package/dist/index.mjs
CHANGED
|
@@ -1412,12 +1412,12 @@ var SysSharingRule = ObjectSchema2.create({
|
|
|
1412
1412
|
group: "Target"
|
|
1413
1413
|
}),
|
|
1414
1414
|
recipient_type: Field2.select(
|
|
1415
|
-
["user", "team", "department", "role", "queue"],
|
|
1415
|
+
["user", "team", "department", "role", "role_and_subordinates", "queue"],
|
|
1416
1416
|
{
|
|
1417
1417
|
label: "Recipient Type",
|
|
1418
1418
|
required: true,
|
|
1419
1419
|
defaultValue: "department",
|
|
1420
|
-
description: "Kind of principal that receives access \u2014 expanded to user grants at evaluation time. `department` walks the parent_department_id tree; `team` is flat (better-auth).",
|
|
1420
|
+
description: "Kind of principal that receives access \u2014 expanded to user grants at evaluation time. `department` walks the parent_department_id tree; `team` is flat (better-auth); `role` is the role's direct members; `role_and_subordinates` walks the sys_role.parent hierarchy to also include every subordinate role (ADR-0056 D6).",
|
|
1421
1421
|
group: "Recipient"
|
|
1422
1422
|
}
|
|
1423
1423
|
),
|
|
@@ -1675,7 +1675,7 @@ var OWNER_FIELD = "owner_id";
|
|
|
1675
1675
|
function effectiveSharingModel(schema) {
|
|
1676
1676
|
const m = schema?.sharingModel ?? schema?.security?.sharingModel;
|
|
1677
1677
|
if (m === "private") return "private";
|
|
1678
|
-
if (m === "read") return "read";
|
|
1678
|
+
if (m === "read" || m === "public_read") return "read";
|
|
1679
1679
|
return "public";
|
|
1680
1680
|
}
|
|
1681
1681
|
function hasOwnerField(schema) {
|
|
@@ -1942,8 +1942,77 @@ async function expandPrincipal(input, ctx) {
|
|
|
1942
1942
|
return [`${t}:${v}`];
|
|
1943
1943
|
}
|
|
1944
1944
|
|
|
1945
|
-
// src/
|
|
1945
|
+
// src/role-graph.ts
|
|
1946
1946
|
var SYSTEM_CTX3 = { isSystem: true, roles: [], permissions: [] };
|
|
1947
|
+
var RoleGraphService = class {
|
|
1948
|
+
constructor(opts) {
|
|
1949
|
+
var _a, _b;
|
|
1950
|
+
this.engine = opts.engine;
|
|
1951
|
+
this.organizationId = opts.organizationId ?? null;
|
|
1952
|
+
this.cache = opts.cache ?? {};
|
|
1953
|
+
(_a = this.cache).descendants ?? (_a.descendants = /* @__PURE__ */ new Map());
|
|
1954
|
+
(_b = this.cache).expand ?? (_b.expand = /* @__PURE__ */ new Map());
|
|
1955
|
+
this.teamGraph = opts.teamGraph ?? new TeamGraphService({ engine: this.engine, organizationId: this.organizationId });
|
|
1956
|
+
}
|
|
1957
|
+
/** Direct child roles of `roleName` (`sys_role.parent === roleName`). */
|
|
1958
|
+
async childRoles(roleName) {
|
|
1959
|
+
const filter = { parent: roleName };
|
|
1960
|
+
if (this.organizationId) filter.organization_id = this.organizationId;
|
|
1961
|
+
let rows = [];
|
|
1962
|
+
try {
|
|
1963
|
+
rows = await this.engine.find("sys_role", {
|
|
1964
|
+
filter,
|
|
1965
|
+
fields: ["name"],
|
|
1966
|
+
limit: 5e3,
|
|
1967
|
+
context: SYSTEM_CTX3
|
|
1968
|
+
});
|
|
1969
|
+
} catch {
|
|
1970
|
+
rows = [];
|
|
1971
|
+
}
|
|
1972
|
+
return Array.from(new Set((rows ?? []).map((r) => String(r.name ?? "")).filter(Boolean)));
|
|
1973
|
+
}
|
|
1974
|
+
/** `roleName` plus every role beneath it in the hierarchy (BFS, cycle-safe). */
|
|
1975
|
+
async descendantRoles(roleName) {
|
|
1976
|
+
if (!roleName) return [];
|
|
1977
|
+
const cached = this.cache.descendants.get(roleName);
|
|
1978
|
+
if (cached) return cached;
|
|
1979
|
+
const out = [];
|
|
1980
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1981
|
+
const queue = [roleName];
|
|
1982
|
+
while (queue.length) {
|
|
1983
|
+
const r = queue.shift();
|
|
1984
|
+
if (seen.has(r)) continue;
|
|
1985
|
+
seen.add(r);
|
|
1986
|
+
out.push(r);
|
|
1987
|
+
for (const child of await this.childRoles(r)) {
|
|
1988
|
+
if (!seen.has(child)) queue.push(child);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
this.cache.descendants.set(roleName, out);
|
|
1992
|
+
return out;
|
|
1993
|
+
}
|
|
1994
|
+
/** Users holding `roleName` OR any subordinate role (the `role_and_subordinates` set). */
|
|
1995
|
+
async expandRoleAndSubordinates(roleName, organizationId) {
|
|
1996
|
+
if (!roleName) return [];
|
|
1997
|
+
const org = organizationId ?? this.organizationId ?? "*";
|
|
1998
|
+
const key = `${org}::${roleName}`;
|
|
1999
|
+
const cached = this.cache.expand.get(key);
|
|
2000
|
+
if (cached) return cached;
|
|
2001
|
+
const roles = await this.descendantRoles(roleName);
|
|
2002
|
+
const users = /* @__PURE__ */ new Set();
|
|
2003
|
+
for (const role of roles) {
|
|
2004
|
+
for (const uid2 of await this.teamGraph.expandRoleUsers(role, organizationId ?? this.organizationId ?? void 0)) {
|
|
2005
|
+
users.add(uid2);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
const result = Array.from(users);
|
|
2009
|
+
this.cache.expand.set(key, result);
|
|
2010
|
+
return result;
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
|
|
2014
|
+
// src/department-graph.ts
|
|
2015
|
+
var SYSTEM_CTX4 = { isSystem: true, roles: [], permissions: [] };
|
|
1947
2016
|
var DepartmentGraphService = class {
|
|
1948
2017
|
constructor(opts) {
|
|
1949
2018
|
var _a, _b, _c;
|
|
@@ -1965,7 +2034,7 @@ var DepartmentGraphService = class {
|
|
|
1965
2034
|
filter: this.orgScope({ id: departmentId }),
|
|
1966
2035
|
fields: ["id", "active"],
|
|
1967
2036
|
limit: 1,
|
|
1968
|
-
context:
|
|
2037
|
+
context: SYSTEM_CTX4
|
|
1969
2038
|
});
|
|
1970
2039
|
const seedRow = Array.isArray(seedRows) ? seedRows[0] : null;
|
|
1971
2040
|
if (!seedRow) seedActive = false;
|
|
@@ -1987,7 +2056,7 @@ var DepartmentGraphService = class {
|
|
|
1987
2056
|
filter: this.orgScope({ parent_department_id: parent, active: { $ne: false } }),
|
|
1988
2057
|
fields: ["id"],
|
|
1989
2058
|
limit: 1e3,
|
|
1990
|
-
context:
|
|
2059
|
+
context: SYSTEM_CTX4
|
|
1991
2060
|
});
|
|
1992
2061
|
} catch {
|
|
1993
2062
|
children = [];
|
|
@@ -2016,7 +2085,7 @@ var DepartmentGraphService = class {
|
|
|
2016
2085
|
filter: { department_id: { $in: depts } },
|
|
2017
2086
|
fields: ["user_id"],
|
|
2018
2087
|
limit: 1e4,
|
|
2019
|
-
context:
|
|
2088
|
+
context: SYSTEM_CTX4
|
|
2020
2089
|
});
|
|
2021
2090
|
} catch {
|
|
2022
2091
|
rows = [];
|
|
@@ -2036,7 +2105,7 @@ var DepartmentGraphService = class {
|
|
|
2036
2105
|
filter: { id: departmentId },
|
|
2037
2106
|
fields: ["id", "manager_user_id"],
|
|
2038
2107
|
limit: 1,
|
|
2039
|
-
context:
|
|
2108
|
+
context: SYSTEM_CTX4
|
|
2040
2109
|
});
|
|
2041
2110
|
row = Array.isArray(rows) ? rows[0] : null;
|
|
2042
2111
|
} catch {
|
|
@@ -2054,7 +2123,7 @@ var DepartmentGraphService = class {
|
|
|
2054
2123
|
filter: { id: userId },
|
|
2055
2124
|
fields: ["id", "manager_id"],
|
|
2056
2125
|
limit: 1,
|
|
2057
|
-
context:
|
|
2126
|
+
context: SYSTEM_CTX4
|
|
2058
2127
|
});
|
|
2059
2128
|
const row = Array.isArray(rows) ? rows[0] : null;
|
|
2060
2129
|
return row?.manager_id ? String(row.manager_id) : null;
|
|
@@ -2069,7 +2138,7 @@ var DepartmentGraphService = class {
|
|
|
2069
2138
|
};
|
|
2070
2139
|
|
|
2071
2140
|
// src/sharing-rule-service.ts
|
|
2072
|
-
var
|
|
2141
|
+
var SYSTEM_CTX5 = { isSystem: true, roles: [], permissions: [] };
|
|
2073
2142
|
function uid(prefix) {
|
|
2074
2143
|
const g = globalThis;
|
|
2075
2144
|
if (g.crypto?.randomUUID) return `${prefix}_${g.crypto.randomUUID()}`;
|
|
@@ -2125,7 +2194,7 @@ var SharingRuleService = class {
|
|
|
2125
2194
|
const existing = await this.engine.find("sys_sharing_rule", {
|
|
2126
2195
|
filter: orgId ? { name: input.name, organization_id: orgId } : { name: input.name },
|
|
2127
2196
|
limit: 1,
|
|
2128
|
-
context:
|
|
2197
|
+
context: SYSTEM_CTX5
|
|
2129
2198
|
});
|
|
2130
2199
|
if (Array.isArray(existing) && existing[0]) {
|
|
2131
2200
|
const row = existing[0];
|
|
@@ -2141,7 +2210,7 @@ var SharingRuleService = class {
|
|
|
2141
2210
|
active,
|
|
2142
2211
|
updated_at: now
|
|
2143
2212
|
};
|
|
2144
|
-
await this.engine.update("sys_sharing_rule", patch, { context:
|
|
2213
|
+
await this.engine.update("sys_sharing_rule", patch, { context: SYSTEM_CTX5 });
|
|
2145
2214
|
return rowFromRule({ ...row, ...patch });
|
|
2146
2215
|
}
|
|
2147
2216
|
const newRow = {
|
|
@@ -2159,7 +2228,7 @@ var SharingRuleService = class {
|
|
|
2159
2228
|
created_at: now,
|
|
2160
2229
|
updated_at: now
|
|
2161
2230
|
};
|
|
2162
|
-
await this.engine.insert("sys_sharing_rule", newRow, { context:
|
|
2231
|
+
await this.engine.insert("sys_sharing_rule", newRow, { context: SYSTEM_CTX5 });
|
|
2163
2232
|
return rowFromRule(newRow);
|
|
2164
2233
|
}
|
|
2165
2234
|
async listRules(filter, context) {
|
|
@@ -2172,7 +2241,7 @@ var SharingRuleService = class {
|
|
|
2172
2241
|
filter: where,
|
|
2173
2242
|
orderBy: [{ field: "name", order: "asc" }],
|
|
2174
2243
|
limit: 1e3,
|
|
2175
|
-
context:
|
|
2244
|
+
context: SYSTEM_CTX5
|
|
2176
2245
|
});
|
|
2177
2246
|
return Array.isArray(rows) ? rows.map(rowFromRule) : [];
|
|
2178
2247
|
}
|
|
@@ -2182,13 +2251,13 @@ var SharingRuleService = class {
|
|
|
2182
2251
|
const byId = await this.engine.find("sys_sharing_rule", {
|
|
2183
2252
|
filter: { id: idOrName },
|
|
2184
2253
|
limit: 1,
|
|
2185
|
-
context:
|
|
2254
|
+
context: SYSTEM_CTX5
|
|
2186
2255
|
});
|
|
2187
2256
|
if (Array.isArray(byId) && byId[0]) return rowFromRule(byId[0]);
|
|
2188
2257
|
const byName = await this.engine.find("sys_sharing_rule", {
|
|
2189
2258
|
filter: orgId ? { name: idOrName, organization_id: orgId } : { name: idOrName },
|
|
2190
2259
|
limit: 1,
|
|
2191
|
-
context:
|
|
2260
|
+
context: SYSTEM_CTX5
|
|
2192
2261
|
});
|
|
2193
2262
|
if (Array.isArray(byName) && byName[0]) return rowFromRule(byName[0]);
|
|
2194
2263
|
return null;
|
|
@@ -2198,11 +2267,11 @@ var SharingRuleService = class {
|
|
|
2198
2267
|
if (!row) return;
|
|
2199
2268
|
await this.engine.delete("sys_record_share", {
|
|
2200
2269
|
where: { source: "rule", source_id: row.id },
|
|
2201
|
-
context:
|
|
2270
|
+
context: SYSTEM_CTX5
|
|
2202
2271
|
});
|
|
2203
2272
|
await this.engine.delete("sys_sharing_rule", {
|
|
2204
2273
|
where: { id: row.id },
|
|
2205
|
-
context:
|
|
2274
|
+
context: SYSTEM_CTX5
|
|
2206
2275
|
});
|
|
2207
2276
|
}
|
|
2208
2277
|
async evaluateRule(idOrName, context) {
|
|
@@ -2235,7 +2304,7 @@ var SharingRuleService = class {
|
|
|
2235
2304
|
filter,
|
|
2236
2305
|
fields: ["id"],
|
|
2237
2306
|
limit: 5e3,
|
|
2238
|
-
context:
|
|
2307
|
+
context: SYSTEM_CTX5
|
|
2239
2308
|
});
|
|
2240
2309
|
return Array.isArray(rows) ? rows.map((r) => String(r.id)).filter(Boolean) : [];
|
|
2241
2310
|
} catch (err) {
|
|
@@ -2250,7 +2319,7 @@ var SharingRuleService = class {
|
|
|
2250
2319
|
filter,
|
|
2251
2320
|
fields: ["id"],
|
|
2252
2321
|
limit: 1,
|
|
2253
|
-
context:
|
|
2322
|
+
context: SYSTEM_CTX5
|
|
2254
2323
|
});
|
|
2255
2324
|
return Array.isArray(rows) && rows.length > 0;
|
|
2256
2325
|
} catch {
|
|
@@ -2273,6 +2342,14 @@ var SharingRuleService = class {
|
|
|
2273
2342
|
return dept.expandUsers(rule.recipient_id);
|
|
2274
2343
|
}
|
|
2275
2344
|
if (rule.recipient_type === "role") return team.expandRoleUsers(rule.recipient_id, rule.organization_id ?? void 0);
|
|
2345
|
+
if (rule.recipient_type === "role_and_subordinates") {
|
|
2346
|
+
const roleGraph = new RoleGraphService({
|
|
2347
|
+
engine: this.engine,
|
|
2348
|
+
organizationId: rule.organization_id ?? null,
|
|
2349
|
+
teamGraph: team
|
|
2350
|
+
});
|
|
2351
|
+
return roleGraph.expandRoleAndSubordinates(rule.recipient_id, rule.organization_id ?? void 0);
|
|
2352
|
+
}
|
|
2276
2353
|
return [];
|
|
2277
2354
|
}
|
|
2278
2355
|
async reconcile(rule, matchedIds, users) {
|
|
@@ -2280,7 +2357,7 @@ var SharingRuleService = class {
|
|
|
2280
2357
|
filter: { source: "rule", source_id: rule.id },
|
|
2281
2358
|
fields: ["id", "record_id", "recipient_id", "access_level"],
|
|
2282
2359
|
limit: 1e5,
|
|
2283
|
-
context:
|
|
2360
|
+
context: SYSTEM_CTX5
|
|
2284
2361
|
});
|
|
2285
2362
|
const desired = /* @__PURE__ */ new Map();
|
|
2286
2363
|
for (const rid of matchedIds) {
|
|
@@ -2306,7 +2383,7 @@ var SharingRuleService = class {
|
|
|
2306
2383
|
sourceId: rule.id,
|
|
2307
2384
|
reason: `rule:${rule.name}`
|
|
2308
2385
|
},
|
|
2309
|
-
|
|
2386
|
+
SYSTEM_CTX5
|
|
2310
2387
|
);
|
|
2311
2388
|
updated += 1;
|
|
2312
2389
|
}
|
|
@@ -2323,13 +2400,13 @@ var SharingRuleService = class {
|
|
|
2323
2400
|
sourceId: rule.id,
|
|
2324
2401
|
reason: `rule:${rule.name}`
|
|
2325
2402
|
},
|
|
2326
|
-
|
|
2403
|
+
SYSTEM_CTX5
|
|
2327
2404
|
);
|
|
2328
2405
|
created += 1;
|
|
2329
2406
|
}
|
|
2330
2407
|
}
|
|
2331
2408
|
for (const [, stale] of existingMap.entries()) {
|
|
2332
|
-
await this.sharing.revoke(stale.id,
|
|
2409
|
+
await this.sharing.revoke(stale.id, SYSTEM_CTX5);
|
|
2333
2410
|
revoked += 1;
|
|
2334
2411
|
}
|
|
2335
2412
|
return {
|
|
@@ -2346,7 +2423,7 @@ var SharingRuleService = class {
|
|
|
2346
2423
|
filter: { source: "rule", source_id: rule.id, record_id: recordId },
|
|
2347
2424
|
fields: ["id", "record_id", "recipient_id", "access_level"],
|
|
2348
2425
|
limit: 1e3,
|
|
2349
|
-
context:
|
|
2426
|
+
context: SYSTEM_CTX5
|
|
2350
2427
|
});
|
|
2351
2428
|
const existingMap = /* @__PURE__ */ new Map();
|
|
2352
2429
|
for (const row of existing ?? []) existingMap.set(String(row.recipient_id), row);
|
|
@@ -2369,7 +2446,7 @@ var SharingRuleService = class {
|
|
|
2369
2446
|
sourceId: rule.id,
|
|
2370
2447
|
reason: `rule:${rule.name}`
|
|
2371
2448
|
},
|
|
2372
|
-
|
|
2449
|
+
SYSTEM_CTX5
|
|
2373
2450
|
);
|
|
2374
2451
|
updated += 1;
|
|
2375
2452
|
}
|
|
@@ -2386,14 +2463,14 @@ var SharingRuleService = class {
|
|
|
2386
2463
|
sourceId: rule.id,
|
|
2387
2464
|
reason: `rule:${rule.name}`
|
|
2388
2465
|
},
|
|
2389
|
-
|
|
2466
|
+
SYSTEM_CTX5
|
|
2390
2467
|
);
|
|
2391
2468
|
created += 1;
|
|
2392
2469
|
}
|
|
2393
2470
|
}
|
|
2394
2471
|
}
|
|
2395
2472
|
for (const [, stale] of existingMap.entries()) {
|
|
2396
|
-
await this.sharing.revoke(stale.id,
|
|
2473
|
+
await this.sharing.revoke(stale.id, SYSTEM_CTX5);
|
|
2397
2474
|
revoked += 1;
|
|
2398
2475
|
}
|
|
2399
2476
|
return {
|
|
@@ -2410,11 +2487,11 @@ var SharingRuleService = class {
|
|
|
2410
2487
|
filter: { source: "rule", source_id: ruleId },
|
|
2411
2488
|
fields: ["id"],
|
|
2412
2489
|
limit: 1e5,
|
|
2413
|
-
context:
|
|
2490
|
+
context: SYSTEM_CTX5
|
|
2414
2491
|
});
|
|
2415
2492
|
let revoked = 0;
|
|
2416
2493
|
for (const row of existing ?? []) {
|
|
2417
|
-
await this.sharing.revoke(row.id,
|
|
2494
|
+
await this.sharing.revoke(row.id, SYSTEM_CTX5);
|
|
2418
2495
|
revoked += 1;
|
|
2419
2496
|
}
|
|
2420
2497
|
return revoked;
|
|
@@ -2422,7 +2499,7 @@ var SharingRuleService = class {
|
|
|
2422
2499
|
};
|
|
2423
2500
|
|
|
2424
2501
|
// src/share-link-service.ts
|
|
2425
|
-
var
|
|
2502
|
+
var SYSTEM_CTX6 = { isSystem: true, roles: [], permissions: [] };
|
|
2426
2503
|
var TOKEN_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
2427
2504
|
var TOKEN_LENGTH = 24;
|
|
2428
2505
|
var DEFAULT_MAX_EXPIRY_DAYS = 365;
|
|
@@ -2562,7 +2639,7 @@ var ShareLinkService = class {
|
|
|
2562
2639
|
where: { id: input.recordId },
|
|
2563
2640
|
fields: ["id"],
|
|
2564
2641
|
limit: 1,
|
|
2565
|
-
context:
|
|
2642
|
+
context: SYSTEM_CTX6
|
|
2566
2643
|
});
|
|
2567
2644
|
if (!Array.isArray(exists) || exists.length === 0) {
|
|
2568
2645
|
throw makeError(404, "RECORD_NOT_FOUND", `${input.object}/${input.recordId} does not exist`);
|
|
@@ -2588,7 +2665,7 @@ var ShareLinkService = class {
|
|
|
2588
2665
|
last_used_at: null,
|
|
2589
2666
|
use_count: 0
|
|
2590
2667
|
};
|
|
2591
|
-
await this.engine.insert("sys_share_link", row, { context:
|
|
2668
|
+
await this.engine.insert("sys_share_link", row, { context: SYSTEM_CTX6 });
|
|
2592
2669
|
return row;
|
|
2593
2670
|
}
|
|
2594
2671
|
async revokeLink(idOrToken, _context) {
|
|
@@ -2598,7 +2675,7 @@ var ShareLinkService = class {
|
|
|
2598
2675
|
where: filter,
|
|
2599
2676
|
fields: ["id", "revoked_at"],
|
|
2600
2677
|
limit: 1,
|
|
2601
|
-
context:
|
|
2678
|
+
context: SYSTEM_CTX6
|
|
2602
2679
|
});
|
|
2603
2680
|
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
2604
2681
|
if (!row) return;
|
|
@@ -2606,7 +2683,7 @@ var ShareLinkService = class {
|
|
|
2606
2683
|
await this.engine.update(
|
|
2607
2684
|
"sys_share_link",
|
|
2608
2685
|
{ id: row.id, revoked_at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
2609
|
-
{ context:
|
|
2686
|
+
{ context: SYSTEM_CTX6 }
|
|
2610
2687
|
);
|
|
2611
2688
|
}
|
|
2612
2689
|
async listLinks(filter, context) {
|
|
@@ -2619,7 +2696,7 @@ var ShareLinkService = class {
|
|
|
2619
2696
|
where,
|
|
2620
2697
|
limit: 200,
|
|
2621
2698
|
sort: [{ field: "created_at", order: "desc" }],
|
|
2622
|
-
context: context.isSystem ?
|
|
2699
|
+
context: context.isSystem ? SYSTEM_CTX6 : context
|
|
2623
2700
|
});
|
|
2624
2701
|
return Array.isArray(rows) ? rows : [];
|
|
2625
2702
|
}
|
|
@@ -2628,7 +2705,7 @@ var ShareLinkService = class {
|
|
|
2628
2705
|
const rows = await this.engine.find("sys_share_link", {
|
|
2629
2706
|
where: { token },
|
|
2630
2707
|
limit: 1,
|
|
2631
|
-
context:
|
|
2708
|
+
context: SYSTEM_CTX6
|
|
2632
2709
|
});
|
|
2633
2710
|
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
2634
2711
|
if (!row) return null;
|
|
@@ -2658,7 +2735,7 @@ var ShareLinkService = class {
|
|
|
2658
2735
|
last_used_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2659
2736
|
use_count: (row.use_count ?? 0) + 1
|
|
2660
2737
|
},
|
|
2661
|
-
{ context:
|
|
2738
|
+
{ context: SYSTEM_CTX6 }
|
|
2662
2739
|
);
|
|
2663
2740
|
} catch {
|
|
2664
2741
|
}
|
|
@@ -2667,7 +2744,7 @@ var ShareLinkService = class {
|
|
|
2667
2744
|
};
|
|
2668
2745
|
|
|
2669
2746
|
// src/share-link-routes.ts
|
|
2670
|
-
var
|
|
2747
|
+
var SYSTEM_CTX7 = { isSystem: true, roles: [], permissions: [] };
|
|
2671
2748
|
var defaultContext = (req) => {
|
|
2672
2749
|
const header = (name) => {
|
|
2673
2750
|
const v = req.headers?.[name];
|
|
@@ -2768,7 +2845,7 @@ function registerShareLinkRoutes(http, service, engine, opts = {}) {
|
|
|
2768
2845
|
const probe = await engine.find("sys_share_link", {
|
|
2769
2846
|
where: { token: req.params.token },
|
|
2770
2847
|
limit: 1,
|
|
2771
|
-
context:
|
|
2848
|
+
context: SYSTEM_CTX7
|
|
2772
2849
|
});
|
|
2773
2850
|
const row = Array.isArray(probe) && probe[0] ? probe[0] : null;
|
|
2774
2851
|
if (row && !row.revoked_at && (!row.expires_at || Date.parse(row.expires_at) > Date.now())) {
|
|
@@ -2792,7 +2869,7 @@ function registerShareLinkRoutes(http, service, engine, opts = {}) {
|
|
|
2792
2869
|
const rows = await engine.find(resolved.link.object_name, {
|
|
2793
2870
|
where: { id: resolved.link.record_id },
|
|
2794
2871
|
limit: 1,
|
|
2795
|
-
context:
|
|
2872
|
+
context: SYSTEM_CTX7
|
|
2796
2873
|
});
|
|
2797
2874
|
const record = Array.isArray(rows) && rows[0] ? rows[0] : null;
|
|
2798
2875
|
if (!record) {
|
|
@@ -2829,12 +2906,12 @@ function registerShareLinkRoutes(http, service, engine, opts = {}) {
|
|
|
2829
2906
|
sendError(res, 400, "UNSUPPORTED", "This share link does not expose messages");
|
|
2830
2907
|
return;
|
|
2831
2908
|
}
|
|
2832
|
-
const
|
|
2909
|
+
const SYSTEM_CTX9 = { isSystem: true, roles: [], permissions: [] };
|
|
2833
2910
|
const rows = await engine.find("ai_messages", {
|
|
2834
2911
|
where: { conversation_id: resolved.link.record_id },
|
|
2835
2912
|
sort: [{ field: "created_at", order: "asc" }],
|
|
2836
2913
|
limit: 500,
|
|
2837
|
-
context:
|
|
2914
|
+
context: SYSTEM_CTX9
|
|
2838
2915
|
});
|
|
2839
2916
|
res.status(200).json({ data: rows ?? [] });
|
|
2840
2917
|
} catch (err) {
|
|
@@ -2849,7 +2926,7 @@ function registerShareLinkRoutes(http, service, engine, opts = {}) {
|
|
|
2849
2926
|
}
|
|
2850
2927
|
|
|
2851
2928
|
// src/rule-hooks.ts
|
|
2852
|
-
var
|
|
2929
|
+
var SYSTEM_CTX8 = { isSystem: true, roles: [], permissions: [] };
|
|
2853
2930
|
var SHARING_RULE_HOOK_PACKAGE = "plugin-sharing:rules";
|
|
2854
2931
|
function bindRuleHooks(engine, service, rules, logger) {
|
|
2855
2932
|
const objects = /* @__PURE__ */ new Set();
|
|
@@ -2864,7 +2941,7 @@ function bindRuleHooks(engine, service, rules, logger) {
|
|
|
2864
2941
|
const data = ctx?.result ?? ctx?.input?.data ?? {};
|
|
2865
2942
|
const id = String(data?.id ?? ctx?.input?.id ?? "");
|
|
2866
2943
|
if (!id) return;
|
|
2867
|
-
await service.evaluateAllForRecord(objectName, id,
|
|
2944
|
+
await service.evaluateAllForRecord(objectName, id, SYSTEM_CTX8);
|
|
2868
2945
|
} catch (err) {
|
|
2869
2946
|
logger?.warn?.("[sharing-rule] hook evaluation failed", { object: objectName, error: err?.message });
|
|
2870
2947
|
}
|