From 38989efcffea3cfafbe43961ed7aa8b892896fa9 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Sat, 9 May 2026 17:13:01 +0530 Subject: [PATCH] fix(rules): add missing rule for users/{uid}/preferences subcollection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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> --- firestore.rules | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/firestore.rules b/firestore.rules index f55c24c..1730472 100644 --- a/firestore.rules +++ b/firestore.rules @@ -81,6 +81,16 @@ service cloud.firestore { allow create: if isSignedIn() && request.auth.uid == userId; allow update, delete: if isSignedIn() && (request.auth.uid == userId || isAdmin()); } + + // User preferences subcollection - per-user settings (e.g. Finance custom + // accounts read/written by `firestore-service.js#loadFinanceCustomAccounts` + // and `#saveFinanceCustomAccounts`). Without this rule the parent + // `/users/{userId}` block does NOT propagate, so the default-deny applies + // and every user's custom-finance-accounts feature silently breaks + // (loader catches the permission error and returns []). + match /users/{userId}/preferences/{prefId} { + allow read, write: if isSignedIn() && request.auth.uid == userId; + } // Item frequency collection - all authenticated users can read/write (shared data) match /itemFrequency/{docId} {