fix(shared): link-field where query must use (customer.Id,eq,N) not (customer,eq,N)
- calculateEffectiveGrants queried CustomerProducts/AccessGrants with
(customer,eq,N), which matches the link field's DISPLAY NAME and always
returns 0 rows -> desiredPaths always [] -> W1/W2/W3 write empty scopes.
- Regression from the shared-lib refactor (3ecee30): W2 had already fixed
this in 36a6b3b but the shared extract reverted to the old syntax.
- Correct syntax (customer.Id,eq,N) verified against live NocoDB for
customer 6 -> /Class/Health, /Class/Other, /Template/Music.
- Updated all three test mocks to match the corrected where clause.
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -76,7 +76,10 @@ async function calculateEffectiveGrants(ctx, customerId) {
|
||||
|
||||
// (a) CustomerProducts -> Resources (via product M2M link), MAX expiry on
|
||||
// the same path.
|
||||
const cps = (await ncGet(ctx, `/api/v2/tables/${T_CUSTPROD}/records?where=(customer,eq,${customerId})&limit=1000`)).list || [];
|
||||
// NOTE: `(customer,eq,N)` matches the link field's DISPLAY NAME and always
|
||||
// returns 0 rows. Must use the `customer.Id` sub-field syntax (or the
|
||||
// foreign-key column `nc_jitu___Customers_id`).
|
||||
const cps = (await ncGet(ctx, `/api/v2/tables/${T_CUSTPROD}/records?where=(customer.Id,eq,${customerId})&limit=1000`)).list || [];
|
||||
for (const c of cps) {
|
||||
if (c.status && c.status !== 'active') continue;
|
||||
if (c.expires_at && String(c.expires_at) <= today) continue; // expired (incl. today)
|
||||
@@ -95,7 +98,7 @@ async function calculateEffectiveGrants(ctx, customerId) {
|
||||
}
|
||||
|
||||
// (b) AccessGrants -> Resources (manual / materialised direct grants)
|
||||
const grants = (await ncGet(ctx, `/api/v2/tables/${T_GRANT}/records?where=(customer,eq,${customerId})&limit=1000`)).list || [];
|
||||
const grants = (await ncGet(ctx, `/api/v2/tables/${T_GRANT}/records?where=(customer.Id,eq,${customerId})&limit=1000`)).list || [];
|
||||
for (const g of grants) {
|
||||
if (g.status && g.status !== 'active') continue;
|
||||
if (g.expires_at && String(g.expires_at) <= today) continue;
|
||||
|
||||
@@ -64,11 +64,11 @@ function makeCtx() {
|
||||
}
|
||||
if (u.includes('/tr/records?limit=10000')) return { list: RESOURCES };
|
||||
// CustomerProducts where customer eq
|
||||
if (u.includes('/tcpc/records?where=(customer,eq,')) {
|
||||
if (u.includes('/tcpc/records?where=(customer.Id,eq,')) {
|
||||
return { list: CUSTOMERPRODUCTS };
|
||||
}
|
||||
// AccessGrants where customer eq
|
||||
if (u.includes('/tag/records?where=(customer,eq,')) {
|
||||
if (u.includes('/tag/records?where=(customer.Id,eq,')) {
|
||||
return { list: ACCESSGRANTS };
|
||||
}
|
||||
// Product M2M link
|
||||
|
||||
@@ -64,11 +64,11 @@ function mockHttp(opts) {
|
||||
if (u.includes('/tr/records?limit=10000')) return { list: state.resources };
|
||||
|
||||
// CP where customer eq
|
||||
const cpm = u.match(/tcpc\/records\?where=\(customer,eq,(\d+)\)/);
|
||||
const cpm = u.match(/tcpc\/records\?where=\(customer\.Id,eq,(\d+)\)/);
|
||||
if (cpm) return { list: state.cps.filter(c => c.customer === Number(cpm[1])) };
|
||||
|
||||
// grants where customer eq
|
||||
const gm = u.match(/tag\/records\?where=\(customer,eq,(\d+)\)/);
|
||||
const gm = u.match(/tag\/records\?where=\(customer\.Id,eq,(\d+)\)/);
|
||||
if (gm) return { list: state.grants.filter(g => g.customer === Number(gm[1])) };
|
||||
|
||||
// product M2M
|
||||
|
||||
@@ -54,9 +54,9 @@ sandbox.helpers = {
|
||||
if (u.endsWith('/api/auth/login')) return { data: { token: 'ADMIN_TOKEN' } };
|
||||
if (u.includes('/tr/records?limit=10000')) return { list: RESOURCES };
|
||||
if (u.includes('/tc/records?limit=10000')) return { list: CUSTOMERS };
|
||||
const cpm = u.match(/tcpc\/records\?where=\(customer,eq,(\d+)\)/);
|
||||
const cpm = u.match(/tcpc\/records\?where=\(customer\.Id,eq,(\d+)\)/);
|
||||
if (cpm) return { list: CPS[Number(cpm[1])] || [] };
|
||||
const gm = u.match(/tag\/records\?where=\(customer,eq,(\d+)\)/);
|
||||
const gm = u.match(/tag\/records\?where=\(customer\.Id,eq,(\d+)\)/);
|
||||
if (gm) return { list: GRANTS[Number(gm[1])] || [] };
|
||||
const pm = u.match(/tp\/links\/lnk\/records\/(\d+)/);
|
||||
if (pm) return { list: PRODUCT_RES[Number(pm[1])] || [] };
|
||||
|
||||
Reference in New Issue
Block a user