bouncer
bouncer copied to clipboard
List Model instances a user owns/manage
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 Did you find a solution?
@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.