got the solution now. Sharing for anyone who might get benefit of the approach. Thanks
{ "rules": { ".read": false, // disables general read access ".write": false, // disables general write access
"Users": {
".read": "auth != null", // Users can read all profiles
"$userUid": {
".write": "auth != null && auth.uid === $userUid", // Users can write only their own data
".validate": "newData.child('userUid').val() === auth.uid &&
(!newData.child('userID').exists() || newData.child('userID').isNumber()) &&
(!newData.child('userName').exists() ||
(newData.child('userName').isString() && newData.child('userName').val().length > 0)) &&
(!newData.child('userFCMToken').exists() ||
(newData.child('userFCMToken').isString() && newData.child('userFCMToken').val().length > 0)) &&
(!newData.child('userPhoneLanguage').exists() || newData.child('userPhoneLanguage').isString()) &&
(!newData.child('userProfileImage').exists() ||
(newData.child('userProfileImage').isString() &&
newData.child('userProfileImage').val().matches(/^https:\\/\\/xxxx\\//))) &&
(!newData.child('userBusiness1Id').exists() || newData.child('userBusiness1Id').isNumber()) &&
(!newData.child('userBusiness1Name').exists() ||
(newData.child('userBusiness1Name').isString() && newData.child('userBusiness1Name').val().length > 0)) &&
(!newData.child('userBusiness1ProfileImage').exists() ||
(newData.child('userBusiness1ProfileImage').isString() &&
newData.child('userBusiness1ProfileImage').val().matches(/^https:\\/\\/xxx\\//))) &&
(!newData.child('userBusiness2Id').exists() || newData.child('userBusiness2Id').isNumber()) &&
(!newData.child('userBusiness2Name').exists() ||
(newData.child('userBusiness2Name').isString() && newData.child('userBusiness2Name').val().length > 0)) &&
(!newData.child('userBusiness2ProfileImage').exists() ||
(newData.child('userBusiness2ProfileImage').isString() &&
newData.child('userBusiness2ProfileImage').val().matches(/^https:\\/\\/xxxx\\//)))"
}
},
"User-Messages": {
"$userId": {
".read": "auth != null && (
auth.uid === $userId ||
auth.uid + '_' + root.child('Users').child(auth.uid).child('userBusiness1Id').val() === $userId ||
auth.uid + '_' + root.child('Users').child(auth.uid).child('userBusiness2Id').val() === $userId
)",
"$recipientId": {
".write": "auth != null && (
auth.uid === $userId || // Sender can write to their own path
auth.uid === $recipientId || // Sender can write to the recipient's path
$recipientId === auth.uid + '_' + root.child('Users').child(auth.uid).child('userBusiness1Id').val() || // When sender is business1, sender can write to user's path
$recipientId === auth.uid + '_' + root.child('Users').child(auth.uid).child('userBusiness2Id').val() || // When sender is business2, sender can write to user's path
auth.uid + '_' + root.child('Users').child(auth.uid).child('userBusiness1Id').val() === $userId || // Business1 sender
auth.uid + '_' + root.child('Users').child(auth.uid).child('userBusiness2Id').val() === $userId // Business2 sender
)",
"$messageId": {
".validate": "newData.child('chatId').exists() && newData.child('chatId').isString() && newData.child('chatId').val().length > 0 &&
newData.child('fromId').exists() && newData.child('fromId').isString() && newData.child('fromId').val().length > 0 &&
newData.child('toId').exists() && newData.child('toId').isString() && newData.child('toId').val().length > 0 &&
newData.child('timestamp').exists() && newData.child('timestamp').isNumber() && newData.child('timestamp').val() > 0 &&
newData.child('text').exists() && newData.child('text').isString() &&
newData.child('text').val().length > 0 &&
newData.child('messageIsRead').exists() && newData.child('messageIsRead').isBoolean() &&
(!newData.child('membershipRequest').exists() || (newData.child('membershipRequest').isString()))"
}
}
}
},