问题
enter image description hereI'm about 90% with my app, and was ready to release it so it can be released to get tested.
I was rejected by apple, because i didn't have a very important feature: - A mechanism for users to block abusive users.
I already have a function in which I follow other users, but I'm stuck on how do I block access, so that when one users blocks the other, they don't see anything related to the one who just blocked him. They can't see their profile in search, in new messages, and their posts.
i don't know where to begin. If you've worked on a user-content generated app. I don't even know where to begin. I've been stuck on this for 3 weeks and now I'm desperate.
//how would I implement something like this?
my security rules are basic.
{
"rules": {
".read": "auth != null",
".write": "auth != null"
} }
the way i display information, as of right now, is that users have to log in with just an email and username and password using and that creates' and user that allows them to log in, into the app and see everything related to the app.
my nodes as well
Messages
comments flagged-posts following likes posts user-messages users
回答1:
There are lots of solutions to this problem. One way is to have a separate node in the database for blocked users. Under each user, you can list the uid
of the blocked user with a value of "true". Doesn't really matter what the value is--this just makes it easier to search for who is blocked. So, for example, say this is your database structure:
users:
uid1:
my data: {
// some stuff here
}
uid2:
my data: {
// some stuff here
}
blocked:
uid1:
uid8: true,
uid3: true
uid2:
uid1: true
In the above example, uid1
has blocked uid8
and uid3
, and so on.
Then you can align your rules to verify that the user can read if they are authenticated and their uid
isn't found on that user's blocked list.
{
"rules": {
"users": {
"$user_id": {
// only messages from the last ten minutes can be read
".read": "auth != null && !root.child('blocked/'+$user_id+'/'+auth.uid+'/true').exists()",
".write": "$user_id === auth.uid"
}
}
}
}
Check out the documentation on security rules for some examples of security rules.
回答2:
I asume somewhere in your DB you have a User Model correct? simply add another field called isBlocked or whatever and according to that value you'd validate if certain users can see that user or not
回答3:
This is what I came up with and it works fine for me. It isn't like instagram where the blocked user completely disappears from your feed but it will definitely keep Apple at bay because one user can block another user and once that happens neither can send a message to one another.
It also gives you the option to show a "block" or "unblock" when the action sheet is presented so that way the current user knows wether they did or didn't block the other user.
First thing is I'm assuming this is inside some sort of chat view controller that has a send message button and inside that chat vc there is the sender's id (current user) and the receiver's id (other user).
To block someone you create a blocked
ref in Firebase, create a node for the user who wants to block the other user and then finally add the blocked user as a key/value pair under that node. The other user's id
is the key
and the value can be true.
For eg. dog123 wants to block cat456. When the dog decides to block the cat the ref to block at would be would be:
let dogId = dog123 // current user
let catId = cat456 // other user
func actionSheetBlockedAction() {
let dictValues = [String: Any]()
dictValues.updateValue(true, forKey: catId)
let ref = Database.database().reference().child("blocked").child(dogId)
ref.updateChildValues(dictValues)
}
This would result in the database looking like:
root
|
@---blocked
|
|
@----dog123
|
|----cat456: true // cat123 is blocked from sending messages to dog123
Inside the same chat vc you need to add some properties and in viewDidLoad or viewWillAppear you need to add 2 separate observers to listen to the blocked ref for both users.
You have to run a check on both user's because yeah dog123 might have blocked cat456 but in return cat456 might also have blocked dog123. Later on if the dog decides to unblock the cat but the cat still has the dog blocked then messages will still get through from the dog to the cat.
To prevent that you add the observers and they'll toggle on some properties that you check when the send button is pressed. If either of the properties are true that means somebody blocked somebody else and no messages should get sent. The properties will let you know who blocked who.
You can also use those properties to show the "block" or "unblock" button when the action sheet appears.
var currentUserId = Auth.auth().currentUser?.uid
var otherUserId = "whatever" // you should already have this
var isCurrentUserBlocked = false
var isOtherUserBlocked = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
checkBlockedRefsForBothUsers() // this is where the isCurrentUserBlocked & isOtherUserBlocked properties get changed
}
@IBAction func sendMessageButtonTapped(sender: UIButton) {
if isOtherUserBlocked {
// alert the current user that they blocked the other user
return
}
if isCurrentUserBlocked {
// alert the current user that the other user blocked them
return
}
// if neither are true then let the current user send their message to the other user
}
func checkBlockedRefsForBothUsers() {
let currentUsersBlockedRef = Database.database().reference().child("blocked").child(currentUserId!)
currentUsersBlockedRef?.observe( .value, with: { (snapshot) in
// if the current user ISN'T under the blocked ref then the other user ISN'T blocked
if !snapshot.exists() {
self.isOtherUserBlocked = false
return
}
for child in snapshot.children {
let snap = child as! DataSnapshot
// if the other user's uid IS under the current user's blocked ref then the other user IS blocked from them
if snap.key == self.otherUsersId {
self.isOtherUserBlocked = true
break
}
// if the other user's uid ISN'T under the current user's blocked ref then the other user ISN'T blocked
self.isOtherUserBlocked = false
}
})
let otherUsersBlockedRef = Database.database().reference().child("blocked").child(otherUserId)
otherUsersBlockedRef?.observe( .value, with: { (snapshot) in
// if the other user's uid ISN'T under the blocked ref then the current user ISN'T blocked
if !snapshot.exists() {
self.isCurrentUserBlocked = false
return
}
for child in snapshot.children {
let snap = child as! DataSnapshot
// if the current user's uid IS under the other user's blocked ref then the current user IS blocked from them
if snap.key == self.currentUserId {
self.isCurrentUserBlocked = true
break
}
// if the current user's uid ISN'T under the other user's blocked ref then the current user ISN'T blocked
self.isCurrentUserBlocked = false
}
})
}
And to show a "block" or "unblock" button when the action sheet is presented use those same 2 properties:
@IBAction func presentActionSheet(sender: UIButton) {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let blockAction = UIAlertAction(title: "Block", style: .default) { (action) in
// run code to block the otherUserId
self.actionSheetBlockedAction()
}
let unblockAction = UIAlertAction(title: "Unblock", style: .default) { (action) in
// run code to unblock the otherUserId
}
if isOtherUserBlocked {
actionSheet.addAction(unblockAction) // if the current user blocked the other user then show the "unblock" action
} else {
actionSheet.addAction(blockAction) // if the current user didn't block the other user then show the "block" action
}
present(actionSheet, animated: true, completion: nil)
}
Finally you might think to yourself that when the dog blocked the cat it would make sense to just update the refs for both of them. The problem with that is when the cat's action sheet is presented, using the logic above it will appear that the cat blocked the dog and the cat's action sheet will show "unblock".
来源:https://stackoverflow.com/questions/50139809/how-to-block-users-on-firebase-in-a-social-media-app-for-ios