I am trying to load a user profile image from firebase storage but I keep running into Cause (1 of 1):
class com.google.firebase.storage.StorageException: User does not have permission to access this object.
Authenticating user with:
mFirebaseAuth.signInWithEmailAndPassword(mEmailView.getText().toString(), mPasswordView.getText().toString())
Here are my firebase rules :
service firebase.storage {
match /b/brainbeats-e9839.appspot.com/o {
match /user/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId;
}
}
}
Loading with glide like this:
StorageReference storageReference = FirebaseStorage.getInstance().getReference();
StorageReference imageStorage = storageReference.child("images/" + user.getArtistProfileImage());
GlideApp.with(this)
.load(imageStorage)
.into(mArtistCoverImage);
Well your rule grants access for the following :
/user/{userId}/{allPaths=**}
so any path under user then a userid location and then anything
But you are accessing
/images/xyzpath
Now since this isn't under /user/ variable userid/ , you get an exception.
why not shift images under user node like :
/user/{userId}/images/yourpath
This should stop giving errors if the auth rule matches. If it's an unauthorized user accessing another userid, it will still crash so best put everything in a try catch block
Related
I have a minimal working example for uploading a zip file to firebase from my Unity-Android app. The sample works fine in playing the app in the Unity-Editor mode.
However, when building for Android, I'm getting the following error:
System.AggregateException: One or more errors occured. (No content provider: /storage/emulated/0/Android/data/com.MyCompany.MyApp/cache/myFile.zip)
Firesbase.Sotrage.StorageException: No content provider
When googling the issue, I get instructions on how to edit a "Custom AndroidManifest.xml" and adding a FileProvider class using native Android code (by compiling a library project using Android Studio etc.).
This looks like a complete overkill for my problem. Shouldn't there be a nice and easy way to share a file, created by my app, stored in the app's own folder with firebase?
So I found a workaround: Instead of trying to send the file directly to firebase, I can
first read the file into RAM as a byte array
then send the bytearray to firebase
Here some code:
FirebaseStorage storage;
StorageReference storageRef;
storage = FirebaseStorage.DefaultInstance;
storageRef = storage.RootReference;
byte[] fileData = File.ReadAllBytes(localFilePath);
StorageReference storageDataRef = storageRef.Child(firebaseFilename);
storageDataRef.PutBytesAsync(fileData)
.ContinueWith((Task<StorageMetadata> task) => {
if (task.IsFaulted || task.IsCanceled) {
Debug.Log(task.Exception.ToString());
// Uh-oh, an error occurred!
}
else {
// Metadata contains file metadata such as size, content-type, and md5hash.
StorageMetadata metadata = task.Result;
string md5Hash = metadata.Md5Hash;
Debug.Log("Finished uploading...");
Debug.Log("md5 hash = " + md5Hash);
}
});
Now I'm not getting any "FileContentProvider" errors anymore. Not sure why I have to do this though...
So i know there is an example available on pub.dev for multiple files method for file picker such as below.
FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true);
if (result != null) {
List<File> files = result.paths.map((path) => File(path)).toList();
} else {
// User canceled the picker
}
What i would like to ask for help is how can i get the files for this allow multiple method and store it into my firebase storage ? I am able to storage and retrieve files with the single method but for multiple files i just cant find the correct way because i would like the user to be able to directly select all the desired files and upload to storage at once. Please help.
How can i continue from the above example ?
I am using firebase resize image extension in my android app first time. I have selected the dimension of 200x200 image size. But in the firebase storage a new filename is not getting created with filename having suffix of 200x200. Its always creating the filename as _200x200 only. so images are getting override all the time.
I have installed the firebase resize image extension in firebase console side only, no firebase function is included into my android studio code.
if (filepath!= null){
storage = FirebaseStorage.getInstance();
storageReference = storage.getReference();
StorageReference ref = storageReference.child(UUID.randomUUID().toString());
ref.putFile(filepath)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
progressDialog.dismiss();
Toast.makeText(context, "Image added successfully", Toast.LENGTH_SHORT).show();
}
});
Since extensions are configured through the Firebase console, it's unlikely (thuogh not impossible) that this code is the cause of the problem.
This type of problem is typically better filed at the Firebase Extensions repo.
In this case it looks like some folks already did file the issue: https://github.com/firebase/extensions/issues/130 I recommend tracking the status of that bug for updates.
for (Uri mUri : mSelected)
{
imagesRef = storageRef.child(postid + mUri.getLastPathSegment());
imagesRef.putFile(mUri).addOnSuccessListener(task4 ->
db.collection("posts").document(postid).update("photo_id", FieldValue.arrayUnion(imagesRef.getDownloadUrl())));
}
So, now i am working with firestore and firebase storage. I uploaded (multiple) images to the storage, and when it is uploaded, i get the download url and wants to add it into my firestore. So, the problem is, only the last image is added into firestore, all images are added into storage, but only the last imgUrl is added into firestore. Since firebase uses async tasks i suspect it is because the update task could not keep up with the loop. Any help is very much appreciated !!!
I think the problem might be with imagesRef, it is declared outside of for (Uri mUri : mSelected) {...} and therefore it is being replaced before addOnSuccessListener(...) responds.
So, declare it locally to for (Uri mUri : mSelected) {...} and see if it will not resolve the issue. Like this
for (Uri mUri : mSelected)
{
var imagesRef = storageRef.child(postid + mUri.getLastPathSegment());
imagesRef.putFile(mUri).addOnSuccessListener(task4 ->
db.collection("posts").document(postid).update("photo_id", FieldValue.arrayUnion(imagesRef.getDownloadUrl())));
}
These are my Firebase Storage rules.
match
/{allPaths=**} {
allow read, write: if request.auth != null;
This is how users are adding pictures to the storage
StorageReference filepathOne = mStorage.child(user_data.getString("uidkey", null)).child("Photos").child("id_one");
As you can see I am using the UID as part of the filepath name. My assumption was that, whenever a user uploads the picture they want, only they would be able to access it as they have the unique UID. However, I created a new user account and for some reason, that user is able to access the photos uploaded by another user even though they have different UID.
I should also point out that I am storing the URI in a sharedpref, and then later converting it into a string to have it display the picture.
This is how I store in the SharedPref
Uri downloadUrl = taskSnapshot.getDownloadUrl();
Picasso.with(getContext())
.load(downloadUrl)
.fit().centerCrop()
.into(image);
editor.putString(user_idone, (taskSnapshot.getDownloadUrl()).toString());
editor.commit();
This is how I extract from the Pref and display.
Picasso.with(getContext())
.load(Uri.parse(user_data.getString("idonekey", null)))
.fit().centerCrop()
.into((ImageView) getView().findViewById(R.id.image));
Currently your rules say "anyone can read/write anything, so long as they are authenticated." It sounds like you want to change the rules to mirror your file structure and provide tighter security:
service firebase.storage {
match /b/<your-bucket-name>/o {
match /{userId}/Photos/{fileName} {
allow read: if request.auth.uid == userId;
}
}
}
Our rules docs talk in greater depth on user and group based security.