diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 00000000..1c341ef5 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "couples-connect-dev" + } +} diff --git a/firebase.json b/firebase.json new file mode 100644 index 00000000..4dd6483f --- /dev/null +++ b/firebase.json @@ -0,0 +1,21 @@ +{ + "firestore": { + "rules": "firestore.rules", + "indexes": "firestore.indexes.json" + }, + "storage": { + "rules": "storage.rules" + }, + "functions": [ + { + "source": "functions", + "codebase": "default", + "ignore": [ + "node_modules", + ".git", + "firebase-debug.log", + "firebase-debug.*.log" + ] + } + ] +} diff --git a/firestore.indexes.json b/firestore.indexes.json new file mode 100644 index 00000000..415027e5 --- /dev/null +++ b/firestore.indexes.json @@ -0,0 +1,4 @@ +{ + "indexes": [], + "fieldOverrides": [] +} diff --git a/storage.rules b/storage.rules new file mode 100644 index 00000000..0d24e27f --- /dev/null +++ b/storage.rules @@ -0,0 +1,28 @@ +rules_version = '2'; +service firebase.storage { + match /b/{bucket}/o { + + // Profile photos: only the owner may write; both the owner and their + // partner can read via the tokenized download URL. Direct read is + // scoped to the owner so raw storage paths aren't publicly accessible. + // + // Size cap: 5 MB. Content-type must be an image (enforced at upload, + // not at read, so the header check only blocks mismatched writes). + match /users/{uid}/profile.jpg { + allow write: if request.auth != null + && request.auth.uid == uid + && request.resource.size < 5 * 1024 * 1024 + && request.resource.contentType.matches('image/.*'); + + // Partners receive the tokenized download URL (generated server-side or + // at upload time) which bypasses these rules. Direct rule-based read is + // scoped to the owner only. + allow read: if request.auth != null && request.auth.uid == uid; + } + + // Deny all other paths by default. + match /{allPaths=**} { + allow read, write: if false; + } + } +}