JosephSilber / bouncer

Laravel Eloquent roles and abilities.
MIT License
3.43k stars 330 forks source link

Fine grade check delete ability #645

Open obrunsmann opened 8 months ago

obrunsmann commented 8 months ago

I almost suspect that there is already a solution, but unfortunately I couldn't find it:

I have a Log model which is a report of an user which needs approval.

My abilities:

      // User's abilities
      "create-app\models\log",
      "approve-app\models\log",
      "delete-approved-app\models\log-owned",

      // Admin's abilities
      "approve-app\models\log-owned",
      "delete-app\models\log-owned",

These are assignable via system settings.

Basics: All users are allowed to create logs. If assigned other users are allowed to approve a log.

Advanced requirements:

  1. It must be (optionally) possible to forbid/allow users to approve their own logs
  2. It must be (optionally) possible to forbid/allow users to delete already approved logs

Problem: I was not able to construct this setup with Bouncer's onboard methods so I plan to add a delete method to my policy which does the magic. But I need to ask (only!) Bouncer if one of the actions are allowed - from Bouncer's side. While bouncer's →can method just passes to Laravel gate it results in an infinite loop.

Idea? If there would be a can method which only checks against bouncer's data I could finalize the log within the Log Policy

class LogPolicy
{
    use HandlesAuthorization;

    public function delete(User $user, Log $log): bool
    {
        $abilities = $user->getAbilities()->pluck('slug');

        if ($log->period->is_closed) {
            return false;
        }

        if ($log->is_approved) {
            return $abilities->contains('delete-approved-app\models\log-owned');
        }

        return $user->is($log->user)
            ? $abilities->contains('delete-app\models\log-owned')
            : $abilities->contains('delete-app\models\log');
    }

My current implementation feels like a workaround to me....