bouncer icon indicating copy to clipboard operation
bouncer copied to clipboard

List Model instances a user owns/manage

Open boyardnicolas opened this issue 5 years ago • 2 comments

Hello,

I'm trying to migrate to the Bouncer but there's probably something I missed in the big picture. What I currently have is User model, an Account model and a Role model. The roles are 'admin', 'manager', 'executive', 'visitor'. A User can only create a lower role User (admin can create manager and lower, manager can create executive and visitor...). Only a 'manager' can create an Account and create relationship between the lower Users he created and the Accounts he created. A User can be for instance a 'manager' of one account and an 'executive' for another. So I have a relationship table account_user :

Schema::create('account_user', function (Blueprint $table) {
            $table->unsignedSmallInteger('account_id');
            $table->unsignedSmallInteger('user_id');
            $table->unsignedTinyInteger('role_id');
            $table->timestamps();
        });
Schema::table('account_user', function (Blueprint $table) {
            $table->foreign('user_id')->references('id')->on('users');
            $table->foreign('account_id')->references('id')->on('accounts');
            $table->foreign('role_id')->references('id')->on('roles');
        });

So this table stores a relationship between a User and an Account, with a Role. When I get to the 'account' page, I want to list all the accounts that the current user have a relationship with:

public function index(Request $request)
    {
        return $request->user()->accounts()->with('wechatOfficialAccount')->get();
    }

with relationship set in User model as:

public function accounts()
    {
        return $this->belongsToMany(Account::class);
    }

Now in order to switch to the Bouncer, I removed my own Role Model, Controller and table, removed my account_user table. Upon creating an account, in the Controller I would replace:

$account = Account::create($validated);
$request->user()->accounts()->attach($account->id, ['role_id' => $request->user()->role->id]);

by:

$account = Account::create($validated);
Bouncer::allow($request->user())->toOwn($account);
// or toManage(), didn't get the difference between Own and Manage,
// Own checks for a user_id in the table, I have many-to-many relationship so can't work,
//  is toManage here to handle many-to-many?

Then still in Account controller, for viewing an Account I would check:

if (Bouncer::can('view', $account)) {
    // ok
}

if User 'own' or 'manage' this instance of Account then any CRUD action is allowed?

Finally, the problem I'm facing is, how do I replace this:

public function index(Request $request)
    {
        return $request->user()->accounts()->with('wechatOfficialAccount')->get();
    }

Meaning, how do I list the Account instances that User manages?

Extra question: If a manager assign one of his executive to an Account he's managing, do I just need to trigger:

if (Bouncer::can('update', $account)) {
    $executive = User::find($userId);
    Bouncer::allow($executive)->toManage($account);
}

My bouncer seeder is as such:

class BouncerSeeder extends Seeder
{
    public function run()
    {
        Bouncer::allow('admin')->everything();
        Bouncer::allow('manager')->to('create-executive');
        Bouncer::allow('manager')->to('create-visitor');
        Bouncer::role()->firstOrCreate(['name' => 'executive']);
        Bouncer::role()->firstOrCreate(['name' => 'visitor']);

        User::find(1)->assign('admin');
    }
}

I'm lost here, any correction/clarification would be greatly appreciated. Thank you.

boyardnicolas avatar Sep 04 '19 11:09 boyardnicolas

@boyardnicolas Did you find a solution?

ldiebold avatar Nov 16 '19 04:11 ldiebold

@ldiebold No, I just kept my relationship table and have some duplicated logic, such as:

    $role = Role::where('name', 'manager')->first();
    $request->user()->accounts()->attach($account->id, ['role_id' => $role->id]);
    Bouncer::allow($request->user())->toManage($account);

In my create method of Account controller, then index method is solely relying on the relationship table.

boyardnicolas avatar Dec 09 '19 05:12 boyardnicolas