fix(rules): add missing rule for users/{uid}/preferences subcollection#3
Open
DDancingDeath wants to merge 1 commit into
Open
fix(rules): add missing rule for users/{uid}/preferences subcollection#3DDancingDeath wants to merge 1 commit into
DDancingDeath wants to merge 1 commit into
Conversation
Without this rule the Finance module's custom-accounts feature is
silently broken in production for ALL users.
ROOT CAUSE
----------
`www/js/firebase/firestore-service.js` reads + writes
`users/{uid}/preferences/financeAccounts` for the Finance tab's
custom-accounts list. The existing `match /users/{userId}` block
does NOT propagate to subcollections in Firestore Security Rules
syntax — each subcollection needs its own `match` block. With no
match for `preferences`, default-deny applies and the SDK throws
`Missing or insufficient permissions`. `loadFinanceCustomAccounts`
catches the error and returns `[]`, so end-users see no custom
accounts and no error.
DISCOVERY
---------
Surfaced by an automated Playwright walkthrough of every tab on the
deployed staging mirror (https://aadhat-staging.web.app) as part of
the Layer-2/Layer-3 verification work. Logged in console as
`Error loading custom finance accounts: FirebaseError: Missing or
insufficient permissions.`.
FIX
---
Add a single `match /users/{userId}/preferences/{prefId}` block
immediately after the existing `/users/{userId}` block. Allows
the owner of the parent doc (uid == userId) to read and write any
preference doc; everyone else is denied. No reduction of existing
access on any other path.
VALIDATION (Rules Playground — RUN BEFORE PUBLISH)
---------------------------------------------------
* uid=A reads /users/A/preferences/financeAccounts → ALLOW
* uid=A writes /users/A/preferences/financeAccounts → ALLOW
* uid=A reads /users/B/preferences/financeAccounts → DENY
* uid=A writes /users/B/preferences/financeAccounts → DENY
* unauthenticated read /users/A/preferences/X → DENY
DEPLOY
------
`firebase deploy --only firestore:rules --project aadhat-management`
VERIFICATION POST-DEPLOY
------------------------
1. Open the Finance tab in the live prod app as any user.
2. Expect no console error and any previously-saved custom accounts
to load (likely empty for users who tried & failed silently before).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
Custom Finance Accounts (the Finance tab's per-user custom-accounts list) is silently broken in production for all users. The Firestore SDK throws
permission-deniedwhenloadFinanceCustomAccountsreadsusers/{uid}/preferences/financeAccounts; the loader catches the error and returns[], so users see no custom accounts and no UI error. Same path is also written to bysaveFinanceCustomAccounts— saves silently fail too.Root cause
Firestore Security Rules do not propagate parent
matchblocks to subcollections. The existingmatch /users/{userId}block (line 79) does not cover/users/{userId}/preferences/{prefId}, so default-deny applies.How discovered
Found by an automated Playwright walkthrough of every top-level tab on the deployed staging mirror (https://aadhat-staging.web.app), logged in as the staging-readonly user. Console emitted
Error loading custom finance accounts: FirebaseError: Missing or insufficient permissions.while every other tab loaded cleanly.The change
Add a single subcollection match block immediately after
/users/{userId}:Strictly additive — does not reduce or modify access on any other path.
Required before merge — Rules Playground validation
Please test in Firebase Console → Firestore → Rules → Rules Playground:
Deploy
firebase deploy --only firestore:rules --project aadhat-managementPost-deploy verification
Open the Finance tab in the live prod app as any user — no console error, custom accounts list loads (will likely be empty, since saves were silently failing before this fix).