如何设置 Firebase 实时数据库规则以读取任何用户的“提及”?

问题描述 投票:0回答:1

我正在设置 Firebase 实时数据库规则,我希望允许任何经过身份验证的用户从任何其他用户的数据中读取提及节点。但是,我不确定我当前的设置是否正确。

这是我目前的规则:

{
    "rules": {
        "users": {
            "$uid": {
                ".read": "auth.uid == $uid",
                ".write": "auth.uid == $uid"
            },
            "mention": {
                ".read": "true",
                ".write": "auth.uid == null"
            }
        }
    }
}

这是我当前的代码:

public void checkMention(String mention, MentionListener mentionListener) {
        database.child("users").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                for (DataSnapshot userSnapshot : snapshot.getChildren()) {
                    String userMention = userSnapshot.child("mention").getValue(String.class);
                    if (userMention != null && userMention.equals(mention)) {
                        if (mentionListener != null) {
                            mentionListener.onMentionData(true);
                        }
                    }
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                Toast.makeText(context, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
                if (mentionListener != null) {
                    mentionListener.onMentionData(false);
                }
            }
        });
    }

主要活动对话框:

private void openDialogUpdate() {
        MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
        DialogUpdateBinding updateBinding = DialogUpdateBinding.inflate(getLayoutInflater());
        AlertDialog dialog = builder.setView(updateBinding.getRoot()).create();

        TextInputLayout usernameInput = updateBinding.usernameInput;
        TextInputEditText inputUsername = updateBinding.inputUsername;
        MaterialButton buttonUpdate = updateBinding.buttonUpdate;

        inputUsername.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                // 
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                //
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (mentionCheckRunnable != null) {
                    handler.removeCallbacks(mentionCheckRunnable);
                }
                mentionCheckRunnable = () -> {
                    String mention = "@" + s.toString().trim().replace(" ", "_").toLowerCase();
                    if (!mention.equals("@")) {
                        accountFirebase.checkMention(mention, exists -> {
                            if (exists) {
                                usernameInput.setError(getString(R.string.unavailable_mention));
                            } else {
                                usernameInput.setHelperText(getString(R.string.available_mention));
                                usernameInput.setError(null);
                            }
                        });
                    }
                    buttonUpdate.setText(mention);
                };
                handler.postDelayed(mentionCheckRunnable, 1500);
            }
        });
        
        buttonUpdate.setOnClickListener(v -> {
            if (inputUsername.getText() != null) {
                String uid = accountFirebase.getUid();
                String username = inputUsername.getText().toString().trim();
                if (!username.isEmpty() && username.length() > 8) {
                    accountFirebase.updateUsername(username, uid).addOnCompleteListener(task -> {
                        if (task.isSuccessful()) {
                            dialog.dismiss();
                        }
                    });
                } else if (!username.isEmpty() && username.length() < 8) {
                    showMessage(updateBinding.getRoot(), getString(R.string.username_too_short));
                } else {
                    showMessage(updateBinding.getRoot(), getString(R.string.username_empty));
                }
            }
        });

        dialog.setCancelable(false);
        dialog.show();
    }

我的目标:

当用户创建帐户时,他转到 MainActivity,会打开一个对话框供他更新他的姓名!

当用户开始输入时,checkMention() 应该搜索所有用户的提及,看看是否已经存在相同的提及。

使得用户只能在提及尚不存在时更新他的名字!

即使我的对话框尚未完成,当前的问题是仅当读取所有用户提及时,toast 在 checkMention() 中返回“权限被拒绝”。

我希望所有用户的提及节点都是公开的。

java android firebase firebase-realtime-database rules
1个回答
0
投票

要允许任何经过身份验证的用户从任何用户数据中读取“提及”节点,您需要将规则移到“$uid”块之外并按如下方式更新:Firebase 实时数据库安全规则

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth.uid == $uid",
        ".write": "auth.uid == $uid",
        "mention": {
          ".read": "auth != null",  // Allows any authenticated user to read the mention
          ".write": "auth.uid == $uid"
        }
      }
    }
  }
}
  • “auth != null”条件允许任何身份验证用户读取任何用户的 mention 节点。确保只有拥有数据的用户才能写入自己的 mention 字段。
© www.soinside.com 2019 - 2024. All rights reserved.