В приложении отказано в разрешении Firebase (Storage), но не в симуляторе? - PullRequest
0 голосов
/ 15 мая 2019

Мой доступ к записи запрещен при попытке загрузить новое фото:

У пользователя нет прав доступа к этому объекту.

Мои правила безопасности:

service firebase.storage {
  match /b/{bucket}/o {
    match /user_photo/{imageid} {
      allow read, write: if request.auth != null && imageid==request.auth.uid;
    }
  }
}

Ссылка на хранилище изображения, которое я хочу "обновить" (загрузить новую фотографию с тем же именем, которое является uid, ниже uid изменено для простоты)

/user_photo/123456

123456 - это идентификатор текущего авторизованного пользователя в моем приложении.

При методе reference.putfile(uri) ссылка:

gs://my-app-name.appspot.com/user_photo/123456

URI:

content://com.android.providers.media.documents/document/image%3A38830

Процесс загрузки фотографий в моем приложении работает нормально (проверено с правилами, установленными так, что все чтения и записи принимаются). С правилами безопасности, в симуляторе консоли, если я установлю флажок с проверкой подлинности && напишите 123456 как идентификатор пользователя, симулятор разрешит все операции. Но из моего приложения я получаю сообщение об ошибке, которое я разместил выше.

Любые предложения о том, что может вызвать это?

EDIT1:

Вся «операция» состоит в том, чтобы загрузить новую фотографию с идентификатором пользователя firebaseuser в качестве фотоизображения в папку «/ user_photo», а затем обновить фотолабораторию в firebaseuser до вновь добавленной фотографии.

Перед изменением правил безопасности этот процесс "работал", и я мог соответственно загрузить фотографию и получить URL-адрес для загрузки из firebaseuser.getPhotoUrl () и загрузить правильную фотографию. После добавления новых правил мне отказывают в приложении (а не в симуляторе в консоли) -

MyInteractor.class:

public Completable changeProfilePhoto(Uri uri){
        return authRepo.getCurrentUser()
                .take(1)
                .flatMapCompletable(firebaseUser -> storageRepo.uploadPhoto(firebaseUser.getUid(), uri)
                        .flatMap(taskSnapshot -> storageRepo.getDownloadUrl(taskSnapshot.getMetadata().getReference()))
                        .flatMapCompletable(uploadedUri -> authRepo.changeUserPhoto(firebaseUser, uploadedUri)))
                .observeOn(AndroidSchedulers.mainThread());
    }

Методы FirebaseAuthRepository (см. Выше authRepo):

@Override
public Observable<FirebaseUser> getCurrentUser() {
    return FirebaseAuthWrapper.observeUserAuthState(firebaseAuth)
            .map(FirebaseAuth::getCurrentUser)
            .switchIfEmpty(observer -> {
                observer.onError(new RxWrapperNullException(RxWrapperNullException.NO_CURRENT_USER));
            })
            .subscribeOn(Schedulers.io());
}

@Override
public Completable changeUserPhoto(FirebaseUser firebaseUser, Uri uri){
    UserProfileChangeRequest request = new UserProfileChangeRequest.Builder()
            .setPhotoUri(uri)
            .build();
    return FirebaseUserWrapper.updateUserProfile(firebaseUser,request);
}

Методы FirebaseStorageRepository (хранилище приведено выше):

@Override
public Single<UploadTask.TaskSnapshot> uploadPhoto(String user, Uri uri) {
    StorageReference thisRef = userPhoto.child(String.format("/%S", user));
    return FirebaseStorageWrapper.putFile(thisRef, uri)
            .subscribeOn(Schedulers.io());
}

@Override
public Single<Uri> getDownloadUrl(StorageReference reference) {
    return FirebaseStorageWrapper.getDownloadUrl(reference)
            .toSingle()
            .subscribeOn(Schedulers.io());
}

Из моего Viewmodel.class я вызываю myInteractor.changeProfilePhoto (uri), где uri - это путь к изображению на устройстве Android, выбранный пользователем из намерение

РЕДАКТИРОВАТЬ 2:

Я заметил, что забыл добавить методы класса-оболочки, что может иметь важное значение:

FirebaseStorageWrapper.class:

public static Single<UploadTask.TaskSnapshot> putFile(StorageReference reference, Uri uri){
    return Single.create(emitter -> {
        StorageTask<UploadTask.TaskSnapshot> task = reference.putFile(uri)
                .addOnSuccessListener(emitter::onSuccess)
                .addOnFailureListener(e -> {
                    if(!emitter.isDisposed()){
                        emitter.onError(e);
                    }
        });
        emitter.setCancellable(task::cancel);
    });
}

public static Maybe<Uri> getDownloadUrl(StorageReference ref) {
    return Maybe.create(emitter -> MaybeTask.assign(emitter, ref.getDownloadUrl()));
}

FirebaseUserWrapper.class:

public static Completable updateUserProfile(FirebaseUser firebaseUser, UserProfileChangeRequest request){
    return Completable.create(emitter -> CompletableTask.assign(emitter, firebaseUser.updateProfile(request)));
}

Метод assign () в CompletableTask и MaybeTask просто устанавливает прослушиватели в Task, а в каждом прослушивателе при вызове по событиям отправляет данные эмиттеру для его отправки.

РЕДАКТИРОВАТЬ 3:

FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
StorageReference storageReference = FirebaseStorage.getInstance().getReference().child("/user_photo").child(String.format("/%S", firebaseUser.getUid()))
storageReference.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        taskSnapshot.getMetadata().getReference().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri newUri) {
                UserProfileChangeRequest request = new UserProfileChangeRequest.Builder()
                        .setPhotoUri(newUri)
                        .build();
                firebaseUser.updateProfile(request).addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        //if it gets here it means operation was successful
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {

                    }
                });
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
            }
        });

    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        //it fails here == storageReference.putFile(uri)
    }
});

1 Ответ

0 голосов
/ 15 мая 2019

Добавить правила хранения ... в вашей базе данных "Правила хранения"

Добавить это : разрешить чтение, запись;

и удалить это : if request.auth! = null && imageid == request.auth.uid;

enter image description here

...