Is there a method/ruleset for Firebase 3 storage to disable file updating or overwriting?
I found data.exists() for Database but no solution for Storage.
TL;DR: In Storage Security Rules, request.resource ~= newData.val() and resource ~= data.val(), so you can use them similarly.
service firebase.storage {
match /b/<bucket>/o {
match /path/to/file {
allow write: if resource == null; // if !data.exists() in DB land
}
}
}
Related
I am trying to upload images with Firebase Storage JS SDK with some rules based on Firestore data.
imageList.forEach(element => {
tasks.push(firebaseStorage.child("Devices").child(dateTime).child(element.name).put(element, { contentType: element.type }))
});
Rules:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /Devices/{deviceId} {
// Authentication is required.
allow create: if request.auth.uid != null &&
// Only Admins are capable of uploading images.
firestore.exists(/databases/(default)/documents/Admins/$(request.auth.uid));
// Authentication is required.
allow read: if request.auth.uid != null &&
// Only Cashiers are capable of reading images.
firestore.exists(/databases/(default)/documents/Cashiers/$(request.auth.uid));
// No update or deletion of files in client (web) for now.
allow update, delete: if false
}
}
}
This is what I get. Any idea what went wrong here? TIA.
Is read and write permission are both required for uploading?
The match /Devices/{deviceId} matches is applied for the files in /Devices directory only. If the rule must be applied to a file within the deviceId sub directory then the path must be:
match /Devices/{deviceId}/{fileName} {
// ...
}
If a rule must be recursively applied to all sub directories, then use a wildcard:
match /Devices/{device=**}
I have 2 apps (admin and clients) using the same firebase database, first configure the admin app, then from the "project configuration" create the clients app in "Add another app".
service cloud.firestore {
match /databases/{database}/documents {
match /clients/{document=**} {
allow read, write: if true;
}
match /payments/{document=**} {
allow read, write: if true;
}
}
}
Without setting firebase rules (like the ones indicated above), the 2 apps work fine, I can read, edit, create and authenticate users. The problem happens when I start to set basic rules:
service cloud.firestore {
match /databases/{database}/documents {
match /clients/{document=**} {
allow read, write: if request.auth != null;
}
match /payments/{document=**} {
allow read, write: if request.auth != null;
}
}
}
with these rules it works fine in the admin app, but in the clients app it shows an error: ERROR FirebaseError: Missing or insufficient permissions; and does not allow read or write to the database.
It seems you are using the syntax for Firestore Security rules in realtime database. I am assuming you want to run 2 apps on a single database and want to have different security rules for both. You need to separate the apps data in their own node to do so. Then you can try the following rules:
{
"rules": {
"app1": {
".read": "auth != null",
".write": "auth != null"
},
"app2": {
".read": true,
".write": true
}
}
}
Now data of both app1 and app2 will have separate security rules. Just make sure the data is in relevant node.
I have a channel for communication between two users and I use Firebase storage to transfer files between these users.
I don't want a third user to have access to the channel's files.
I'm trying to identify authorized users using 'authfile' and the metadata inside it.
That authfile is uploaded using admin sdk.
Only specific users can download and upload files to specific path in storage where the authfiles metadata contains his uid. still the users are not allowed to touch the authfile.
The metadata inside the authfile looks like this:
metadata: {
AvnYaUFdaJh1j0FMIiKWoIC2MDw1: true, // firebase userId 1
YhFyYRbutlf1PFI4NLKTN4qWRhQ2: true, // firebase userId 2
}
my storage
The rules I've tried:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// Channel Media
match /media/{channelId}/{allPaths=**} {
function isAllowedUser(uid) {
return /authfile.resource.metadata.users[uid] == true;
}
allow delete: if isAllowedUser(request.auth.uid)
&& request.resource.contentType != 'authfile'
allow read: if isAllowedUser(request.auth.uid)
&& request.resource.contentType != 'authfile'
allow write: if isAllowedUser(request.auth.uid)
&& request.resource.contentType != 'authfile'
&& request.resource.size < 16 * 1024 * 1024;
}
}
}
I am writing Firebase storage rules for the first time and would like advice on how this could be implemented.
I don't think you need 'users' here.
function isAllowedUser(uid) {
return /authfile.resource.metadata.users[uid] == true;
}
This should be valid
resource.metadata[uid] == true;
Additionally, if you need something like checking existence of another file or it's metadata, consider using Cloud functions as mentioned in this answer.
Where does the service element get put in a database.rules.json file used by the firebase client, which is:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
}
}
I'm assuming the above applies to both Cloud Firestore and real time database?
I have a Cloud Firestore rule I'd like to keep in the json file so that it can be source controlled and deployed automatically. Here's the rule as shown in firestore:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
match /photos {
allow read, write: if request.auth != null;
}
match /users/{user} {
allow read: if request.auth != null;
allow write: if request.auth.uid == user.id)
}
}
}
How do I update my database.rules.json file to start to keep it in sync? Do I need to add a cloud.firestore element under rules? Where does it go? Are firestore rules kept in a completely separate file?
I think you have to put these rules in a separate file named firestore.rules.
The first set of rules (i.e. the ones in database.rules.json) in only for the Real Time Database.
Firebase Realtime Database security rules are completely different than Cloud Firestore security rules. You can't have one file for both, and there is no automated process to keep them in sync, whatever that means for you. When you run firebase init, tell it that you want to init both Realtime Database and Firestore, and it will suggest names of different files for the rules.
In order for me to get Fastly working with firebase storage I had to add the following permissions on each image and the storage bucket: Entity: User, Name: AllUsers, Access: Reader. Is there a way to avoid this tedious and unscalable method, since its all user uploaded media?
My firebase storage security looks like the following:
service firebase.storage {
match /b/myapp.appspot.com/o {
match /proUsers/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId || request.resource.size < 2 * 1024 * 1024 || request.resource.contentType.matches('image/png') || request.resource.contentType.matches('image/jpeg');
}
}
}
the error I receive on fastly is that: Anonymous users does not have storage.objects.list access to bucket and if I try to access image directly I get the error: Anonymous users does not have storage.objects.get access to object
Where do I allow for anonymous users to have read capabilities? I assumed setting allow read did precisely this.
To allow anonymous users to read from your database (but not write) you can change your rules to this:
service firebase.storage {
match /b/myapp.appspot.com/o {
match /proUsers/{userId}/{allPaths=**} {
allow write: if request.auth.uid == userId || request.resource.size < 2 * 1024 * 1024 || request.resource.contentType.matches('image/png') || request.resource.contentType.matches('image/jpeg');
allow read;
}
}
}