Firebase存储:用户无权访问此对象(Android)

时间:2018-11-25 21:19:28

标签: android firebase google-cloud-firestore firebase-security-rules

我正在尝试建立博客应用。这个想法是,在用户登录或注册后,他们将被定向到设置页面,在其中选择个人资料图片和名称。图片将保存到Firestore存储中,然后将详细信息记录在Firestore数据库中。

因此,在设置页面加载时,假设首先检查该用户是否具有现有的数据图片和名称,然后让他们更改或填写其详细信息。

一切正常,直到用户尝试上传他的照片和姓名为止。图片成功存储在Firestore中,然后继续登录Firestore并返回错误

  

用户无权访问此对象。

我的应用程序中的其他活动具有相同的功能,并且它们均返回相同的错误。

我的设置逻辑是这样的:

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_setup);


    firebaseAuth = FirebaseAuth.getInstance();
    user_id = firebaseAuth.getCurrentUser().getUid();

    firebaseFirestore = FirebaseFirestore.getInstance();
    storageReference = FirebaseStorage.getInstance().getReference();


    setupImage = findViewById(R.id.setup_image);
    setupName = findViewById(R.id.setup_name);
    setupBtn = findViewById(R.id.setup_btn);
    setupProgress = findViewById(R.id.setup_progress);

    setupProgress.setVisibility(View.VISIBLE);
    setupBtn.setEnabled(false);

    firebaseFirestore.collection("Users").document(user_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {

            if (task.isSuccessful()) {

                if (task.getResult().exists()) {

                    String name = task.getResult().getString("name");
                    String image = task.getResult().getString("image");

                    mainImageURI = Uri.parse(image);

                    setupName.setText(name);

                    RequestOptions placeholderRequest = new RequestOptions();
                    placeholderRequest.placeholder(R.drawable.dummy);

                    Glide.with(Setup.this).setDefaultRequestOptions(placeholderRequest).load(image).into(setupImage);


                }

            } else {

                String error = task.getException().getMessage();
                Toast.makeText(Setup.this, "(FIRESTORE Retrieve Error) : " + error, Toast.LENGTH_LONG).show();

            }

            setupProgress.setVisibility(View.INVISIBLE);
            setupBtn.setEnabled(true);

        }
    });


    setupBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            final String user_name = setupName.getText().toString();

            if (!TextUtils.isEmpty(user_name) && mainImageURI != null) {

                setupProgress.setVisibility(View.VISIBLE);

                if (isChanged) {

                    user_id = firebaseAuth.getCurrentUser().getUid();

                    File newImageFile = new File(mainImageURI.getPath());
                    try {

                        compressedImageFile = new Compressor(Setup.this)
                                .setMaxHeight(125)
                                .setMaxWidth(125)
                                .setQuality(20)
                                .compressToBitmap(newImageFile);

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    compressedImageFile.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                    byte[] thumbData = baos.toByteArray();

                    final UploadTask image_path = storageReference.child("profile_images").child(user_id + ".jpg").putBytes(thumbData);

                    Task<Uri> urlTask = image_path.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
                        @Override
                        public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
                            if (!task.isSuccessful()) {
                                throw task.getException();
                            }

                            // Continue with the task to get the download URL
                            return storageReference.getDownloadUrl();
                        }
                    }).addOnCompleteListener(new OnCompleteListener<Uri>() {
                        @Override
                        public void onComplete(@NonNull Task<Uri> task) {
                            if (task.isSuccessful()) {
                                Uri downloadUri = task.getResult();
                                storeFirestore(task, user_name, downloadUri);
                            } else {
                                Toast
                                        .makeText
                                                (Setup.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                                setupProgress.setVisibility(View.INVISIBLE);
                            }
                        }
                    });

                } else {

                    storeFirestore(null, user_name, null);

                }

            }else {
                Toast.makeText(Setup.this, "Please make sure to put a name and pick a picture", Toast.LENGTH_LONG).show();
            }

        }

    });

    setupImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                if (ContextCompat.checkSelfPermission(Setup.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

                    Toast.makeText(Setup.this, "Permission Denied", Toast.LENGTH_LONG).show();
                    ActivityCompat.requestPermissions(Setup.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);

                } else {

                    BringImagePicker();

                }

            } else {

                BringImagePicker();

            }

        }

    });


}

private void storeFirestore(@NonNull Task<Uri> task, String user_name, Uri downloadUri) {


    if (task == null) {
        downloadUri = mainImageURI;
    }


    Map<String, String> userMap = new HashMap<>();
    userMap.put("name", user_name);
    userMap.put("image", downloadUri.toString());

    firebaseFirestore.collection("Users").document(user_id).set(userMap).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {

            if (task.isSuccessful()) {

                Toast.makeText(Setup.this, "The user Settings are updated.", Toast.LENGTH_LONG).show();
                Intent mainIntent = new Intent(Setup.this, MainActivity.class);
                startActivity(mainIntent);
                finish();

            } else {

                String error = task.getException().getMessage();
                Toast.makeText(Setup.this, "(FIRESTORE Error) : " + error, Toast.LENGTH_LONG).show();

            }

            setupProgress.setVisibility(View.INVISIBLE);

        }
    });


}

private void BringImagePicker() {

    CropImage.activity()
            .setGuidelines(CropImageView.Guidelines.ON)
            .setAspectRatio(1, 1)
            .start(Setup.this);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
            CropImage.ActivityResult result = CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK) {

                mainImageURI = result.getUri();
                setupImage.setImageURI(mainImageURI);

                isChanged = true;

            } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {

                Exception error = result.getError();

            }
    }

}

因此,setupButton触发上传,并在将图片存储在Firebase Storage中之后调用storeInFirestore方法。

我在Firestore中有这样的规则

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.uid != null;
    }
  }
}

仔细观察,我发现该文件已在Firebase Storage中上传,但是当我尝试获取下载Uri时返回了错误。所以else语句

addOnCompleteListener(new OnCompleteListener<Uri>() {
                        @Override
                        public void onComplete(@NonNull Task<Uri> task) {
                            if (task.isSuccessful()) {
                                Uri downloadUri = task.getResult();
                                storeFirestore(task, user_name, downloadUri);
                            } else {
                                Toast
                                        .makeText
                                                (Setup.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();

是返回错误的原因,因此永远不会触发登录Firestore的方法。

由于我关注文档,因此我尝试获取downloadUri的方式出了问题。

我的存储规则也是如此

    service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

0 个答案:

没有答案