multicaret/laravel-acquaintances

problem with denying where a subsequent request being accepted will result in two friendships

jayenne opened this issue · 3 comments

Hi,
I've noticed a problem with deniying requests.

Because you set the status to 'denied' and don't include an isDeniedBy() method, we can't [out of the box] prevent a sender from re-befriending.

This problem is then compounded when a recipient denies or blocks a sender, then the sender subsequently re-befriends, a new entry is created with the status pending (thus creating two entires for sender_id = x & recipient_id = y) - once that recipient accepts (or blocks etc) the sender, both enties become syncronised (accepted or blocked etc).

This results in multiple valid friendships for a single status

  • A (less than desireable) workaround is to ignore all deny methods and use unfriend instead. This will remove the befriend request thus preventing these multiples
  • If you'd prefer to prevent re-befriendings after the first denial then use blockFriendRequest instead of unfriend. This will maintain a status you can work with.

Yes. If user A send a friend request to user B and user B deny it, then user A can send Many duplicate friend requests to user B.

Extended my model with few methods, including:

use Friendable;

public function checkFriendship($model) {
    $friendshipModelName = Interaction::getFriendshipModelName();
    return $friendshipModelName::where(function ($query) use ($model) {
        $query->where(function ($q) use ($model) {
            $q->whereSender($this);
            $q->whereRecipient($model);
        })->orWhere(function ($q) use ($model) {
            $q->whereRecipient($this);
            $q->whereSender($model);
        });
    });
}

then in controller:

public function addFriend(Request $request, $id)
{
    if ($request->user()->id == $id) {
        return $this->code(406);
    }
    $to_befriend = Player::findOrFail($id);

    $check = $request->user()->checkFriendship($to_befriend)->get();
    if (count($check)) {
        return $this->code(409, 'Friendship already '.$check[0]['status']);
    }

    DB::beginTransaction();
    try {
        $request->user()->befriend($to_befriend);
        DB::commit();
        return $this->code(201);
    } catch(\Exception $e) {
       DB::rollback();
       return $this->code(500);
    }
}

$this->code(500) is own json response method

I just repeated already existent getFriendship method :)

$user = User::findOrFail($id);
$check = $request->user()->getFriendship($user);