Skip to content

Commit 3e4ad0b

Browse files
ekremneyclaude
andcommitted
fix(data-access): return plain camelCase object from allByOrganizationIds*WithTargetOrganization
#fetchGrantsWithTargetOrg was calling createInstanceFromRow(), producing a model instance for the `grant` field. The auth-service (and the method's own docstring) expected a plain camelCase object with direct property access (grant.productCode, grant.expiresAt, grant.organizationId, …). On a model instance those fields are undefined; only getters like getProductCode() exist. This caused the delegated_tenants loop to skip every grant because `grant.productCode !== productCode` was always `undefined !== 'LLMO'` → true, leaving delegated_tenants: [] in every JWT regardless of real DB grants. Fix: destructure the embedded `organizations` key from the PostgREST row, then call fromDbRecord(grantRow, this.fieldMaps.toModelMap) to produce the documented plain camelCase object. Update unit and IT tests to assert direct property access (grant.organizationId, grant.productCode, …) instead of model-instance getters, so the contract is verified at the test level going forward. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3b7d348 commit 3e4ad0b

File tree

3 files changed

+27
-19
lines changed

3 files changed

+27
-19
lines changed

packages/spacecat-shared-data-access/src/models/site-ims-org-access/site-ims-org-access.collection.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import BaseCollection from '../base/base.collection.js';
1414
import DataAccessError from '../../errors/data-access.error.js';
15-
import { DEFAULT_PAGE_SIZE } from '../../util/postgrest.utils.js';
15+
import { DEFAULT_PAGE_SIZE, fromDbRecord } from '../../util/postgrest.utils.js';
1616

1717
/**
1818
* SiteImsOrgAccessCollection - Collection of cross-org delegation grants.
@@ -127,10 +127,13 @@ class SiteImsOrgAccessCollection extends BaseCollection {
127127
async #fetchGrantsWithTargetOrg(query) {
128128
return this.#fetchPaginatedGrants(
129129
query,
130-
(row) => ({
131-
grant: this.createInstanceFromRow(row),
132-
targetOrganization: { id: row.organizations.id, imsOrgId: row.organizations.ims_org_id },
133-
}),
130+
(row) => {
131+
const { organizations, ...grantRow } = row;
132+
return {
133+
grant: fromDbRecord(grantRow, this.fieldMaps.toModelMap),
134+
targetOrganization: { id: organizations.id, imsOrgId: organizations.ims_org_id },
135+
};
136+
},
134137
'Failed to query grants with target organization',
135138
);
136139
}

packages/spacecat-shared-data-access/test/it/site-ims-org-access/site-ims-org-access.test.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@ describe('SiteImsOrgAccess IT', async () => {
165165
for (const entry of entries) {
166166
expect(entry).to.have.property('grant');
167167
expect(entry).to.have.property('targetOrganization');
168-
expect(entry.grant.getOrganizationId()).to.equal(organizationId);
169-
expect(entry.targetOrganization.id).to.equal(entry.grant.getTargetOrganizationId());
168+
// grant is a plain camelCase object — use direct property access, not model getters
169+
expect(entry.grant.organizationId).to.equal(organizationId);
170+
expect(entry.targetOrganization.id).to.equal(entry.grant.targetOrganizationId);
170171
}
171172
});
172173

@@ -183,9 +184,10 @@ describe('SiteImsOrgAccess IT', async () => {
183184
for (const entry of entries) {
184185
expect(entry).to.have.property('grant');
185186
expect(entry).to.have.property('targetOrganization');
186-
expect(entry.grant.getOrganizationId()).to.equal(organizationId);
187-
expect(entry.grant.getTargetOrganizationId()).to.be.a('string');
188-
expect(entry.targetOrganization.id).to.equal(entry.grant.getTargetOrganizationId());
187+
// grant is a plain camelCase object — use direct property access, not model getters
188+
expect(entry.grant.organizationId).to.equal(organizationId);
189+
expect(entry.grant.targetOrganizationId).to.be.a('string');
190+
expect(entry.targetOrganization.id).to.equal(entry.grant.targetOrganizationId);
189191
expect(entry.targetOrganization.imsOrgId).to.be.a('string');
190192
}
191193
});

packages/spacecat-shared-data-access/test/unit/models/site-ims-org-access/site-ims-org-access.collection.test.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,17 @@ describe('SiteImsOrgAccessCollection', () => {
231231
expect(eqStub).to.have.been.calledWith('organization_id', mockRecord.organizationId);
232232
expect(orderStub).to.have.been.calledWith('id');
233233
const { grant, targetOrganization } = results[0];
234-
expect(grant.getId()).to.equal('grant-1');
235-
expect(grant.getSiteId()).to.equal('site-uuid-1');
236-
expect(grant.getOrganizationId()).to.equal(mockRecord.organizationId);
237-
expect(grant.getTargetOrganizationId()).to.equal(mockRecord.targetOrganizationId);
238-
expect(grant.getProductCode()).to.equal('LLMO');
239-
expect(grant.getRole()).to.equal('agency');
240-
expect(grant.getGrantedBy()).to.equal('ims:user123');
241-
expect(grant.getExpiresAt()).to.be.undefined;
234+
// grant is a plain camelCase object (not a model instance) — use direct property access.
235+
// The primary key maps to the model's idName (siteImsOrgAccessId), not 'id'.
236+
// null DB values are excluded by normalizeModelValue (expiresAt is absent, not null).
237+
expect(grant.siteImsOrgAccessId).to.equal('grant-1');
238+
expect(grant.siteId).to.equal('site-uuid-1');
239+
expect(grant.organizationId).to.equal(mockRecord.organizationId);
240+
expect(grant.targetOrganizationId).to.equal(mockRecord.targetOrganizationId);
241+
expect(grant.productCode).to.equal('LLMO');
242+
expect(grant.role).to.equal('agency');
243+
expect(grant.grantedBy).to.equal('ims:user123');
244+
expect(grant.expiresAt).to.be.undefined;
242245
expect(targetOrganization).to.deep.equal({
243246
id: mockRecord.targetOrganizationId,
244247
imsOrgId: 'target@AdobeOrg',
@@ -356,7 +359,7 @@ describe('SiteImsOrgAccessCollection', () => {
356359

357360
expect(results).to.have.lengthOf(1);
358361
expect(inStub).to.have.been.calledWith('organization_id', ids);
359-
expect(results[0].grant.getOrganizationId()).to.equal(mockRecord.organizationId);
362+
expect(results[0].grant.organizationId).to.equal(mockRecord.organizationId);
360363
expect(results[0].targetOrganization.imsOrgId).to.equal('target@AdobeOrg');
361364
});
362365

0 commit comments

Comments
 (0)