Summary
Follow-up to #2084 / PR #2088. That PR fixed the reported orX() zero-args defect in MultiTenancyTrait::applyActiveOrgFilter(), but live-verification on the shared dev instance showed dbal-source (query-backed) schemas — e.g. spectr-live's v-app-market, apps (register 2479, backed by Source spectr intelligence-db, uuid beb5b7d0-19bd-42b6-a7c4-9d10cc840a31) — still return total: 0 with {"saasMode":true,"adminOverride":true}, even after that fix.
Root cause
DbalObjectSourceProvider::resolveSource() (lib/Service/ObjectSource/DbalObjectSourceProvider.php) loads the backing Source entity via:
$matches = $this->sourceMapper->findAll(filters: ['uuid' => $sourceId]);
$source = ($matches[0] ?? null);
SourceMapper uses MultiTenancyTrait, and findAll() applies applyOrganisationFilter(..., allowNullOrg: false) to this query, same as any tenant-owned row. The spectr intelligence-db Source row has its own organisation (286a9152-4b09-4714-9115-fabbbad342d0) which differs from the querying admin's active organisation (9db9eae6-5049-47cd-a434-a68568cf3a01).
Under normal config, adminOverride bypasses this and everything works — that's exactly why the current workaround ({"saasMode":false,"adminOverride":true}) masks the problem. But saasMode: true unconditionally disables admin override (MultiTenancyTrait::isAdminOverrideEnabled()), so the Source row gets excluded by the org filter, findAll() returns [], resolveSource() returns null, resolveContext() logs only a warning ([ObjectSource:dbal-source] no source resolved for schema ...) and returns null, and every downstream find/findAll/count/aggregate on that schema silently returns empty — no exception ever surfaces to the caller. Confirmed live via nextcloud.log.
Why this matters
A Source (external DB connection config) is shared infrastructure, not tenant-owned data — it's the provider multiple dbal-backed schemas connect through, not an object that itself belongs to one tenant's data set. Scoping its own lookup by the querying user's active organisation means any dbal-backed schema becomes invisible to every user whose active org doesn't happen to match the Source's organisation column, independent of whatever RBAC the target schema itself declares.
Suggested fix direction (needs a design decision, not a mechanical patch)
One of:
- Exempt
Source entities from organisation-scoped filtering when resolved internally by DbalObjectSourceProvider (they're infrastructure config, gate on RBAC/admin-only elsewhere), or
- Treat
Source.organisation as informational/ownership metadata only, and let the schema's own authorization/RBAC (already enforced via MagicOrganizationHandler/applyOrganisationFilter on the resulting objects) be the actual access boundary, or
- Give
Source records allowNullOrg: true semantics plus an explicit cross-org-visible flag for shared connections.
Repro
occ config:app:set openregister multitenancy --value='{"saasMode":true,"adminOverride":true}'
curl -u admin:admin 'http://localhost:8080/apps/openregister/api/objects/spectr-live/v-app-market?_limit=3'
# {"results":[],"total":0,...}
# nextcloud.log: [ObjectSource:dbal-source] no source resolved for schema v-app-market
occ config:app:set openregister multitenancy --value='{"saasMode":false,"adminOverride":true}'
Current instance state
Workaround {"saasMode":false,"adminOverride":true} remains in place on the shared dev instance and MUST stay until this is resolved — flipping saasMode back to true empties all dbal-source schemas again (confirmed, unrelated to #2084's fix which is already merged).
Summary
Follow-up to #2084 / PR #2088. That PR fixed the reported
orX()zero-args defect inMultiTenancyTrait::applyActiveOrgFilter(), but live-verification on the shared dev instance showed dbal-source (query-backed) schemas — e.g.spectr-live'sv-app-market,apps(register 2479, backed by Sourcespectr intelligence-db, uuidbeb5b7d0-19bd-42b6-a7c4-9d10cc840a31) — still returntotal: 0with{"saasMode":true,"adminOverride":true}, even after that fix.Root cause
DbalObjectSourceProvider::resolveSource()(lib/Service/ObjectSource/DbalObjectSourceProvider.php) loads the backingSourceentity via:SourceMapperusesMultiTenancyTrait, andfindAll()appliesapplyOrganisationFilter(..., allowNullOrg: false)to this query, same as any tenant-owned row. Thespectr intelligence-dbSourcerow has its ownorganisation(286a9152-4b09-4714-9115-fabbbad342d0) which differs from the querying admin's active organisation (9db9eae6-5049-47cd-a434-a68568cf3a01).Under normal config,
adminOverridebypasses this and everything works — that's exactly why the current workaround ({"saasMode":false,"adminOverride":true}) masks the problem. ButsaasMode: trueunconditionally disables admin override (MultiTenancyTrait::isAdminOverrideEnabled()), so theSourcerow gets excluded by the org filter,findAll()returns[],resolveSource()returnsnull,resolveContext()logs only awarning([ObjectSource:dbal-source] no source resolved for schema ...) and returnsnull, and every downstreamfind/findAll/count/aggregateon that schema silently returns empty — no exception ever surfaces to the caller. Confirmed live vianextcloud.log.Why this matters
A
Source(external DB connection config) is shared infrastructure, not tenant-owned data — it's the provider multiple dbal-backed schemas connect through, not an object that itself belongs to one tenant's data set. Scoping its own lookup by the querying user's active organisation means any dbal-backed schema becomes invisible to every user whose active org doesn't happen to match the Source'sorganisationcolumn, independent of whatever RBAC the target schema itself declares.Suggested fix direction (needs a design decision, not a mechanical patch)
One of:
Sourceentities from organisation-scoped filtering when resolved internally byDbalObjectSourceProvider(they're infrastructure config, gate on RBAC/admin-only elsewhere), orSource.organisationas informational/ownership metadata only, and let the schema's ownauthorization/RBAC (already enforced viaMagicOrganizationHandler/applyOrganisationFilteron the resulting objects) be the actual access boundary, orSourcerecordsallowNullOrg: truesemantics plus an explicit cross-org-visible flag for shared connections.Repro
Current instance state
Workaround
{"saasMode":false,"adminOverride":true}remains in place on the shared dev instance and MUST stay until this is resolved — flippingsaasModeback totrueempties all dbal-source schemas again (confirmed, unrelated to #2084's fix which is already merged).