Closer/storage.rules

39 lines
1.6 KiB
Plaintext
Raw Normal View History

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;
}
feat(chat): encrypted image messages, notification deep link routing, partner photo on home, rate limiter bump, chat bubble drag-to-dismiss - FirestoreQuestionThreadDataSource: sendImageMessage encrypts bytes with couple key, uploads to Storage, stores URL in Firestore; loadDecryptedMedia downloads + decrypts - QuestionMessage: type field (text/image), mediaUrl, isImage helper - QuestionDiscussionThread: image picker (gallery + camera), encrypted image rendering with produceState, messenger-style avatars on consecutive bubbles - QuestionThreadViewModel: sendImage, loadDecryptedMedia, dailyRevealed skip for already-revealed daily questions, partner photo loading - MainActivity: deepLinkRouteFromIntent resolves FCM data extras to navigation routes; pendingDeepLink state for onNewIntent - AppNavigation: LaunchedEffect waits for HOME route before navigating deep link (fixes race with onboarding) - PartnerHomeScreen: partner photoUrl loaded and displayed in identity card - NotificationRateLimiter: 20 partner/day, 100/week (was 2/4 — too tight for game activity) - MessageBubbleOverlay: drag-to-dismiss zone at bottom, no auto-timeout (persists until read) - ActiveThreadMonitor: dismisses bubble when entering conversation - onMessageWritten: includes author name + photo URL in notification payload - firestore.rules: messages create allows type=image with mediaUrl or type=text with ciphertext - storage.rules: chat_media path with 15MB cap - file_paths.xml: cache-path for camera capture
2026-06-24 15:18:41 -05:00
// Encrypted chat media: the author writes under their own path (already E2E-encrypted
// ciphertext, so Storage never holds anything readable). The partner reads via the tokenized
// download URL, which bypasses these rules — same model as profile photos. 15 MB cap.
match /users/{uid}/chat_media/{file} {
allow write: if request.auth != null
&& request.auth.uid == uid
&& request.resource.size < 15 * 1024 * 1024;
allow read: if request.auth != null && request.auth.uid == uid;
}
// Deny all other paths by default.
match /{allPaths=**} {
allow read, write: if false;
}
}
}