Retrieving all users of a specific permission in Laravel 5 / Entrust - php

How can I retrieve the users of a specific permission in Entrust for Laravel 5.0.
use App\Role;
use App\Permission;
$permission = Permission::find(1);
$roles = $permission->roles;
$users = $roles->users;
I know the code doesn't work... Just an example.

try this
$users = User::permission('edit articles')->get(); // Returns only users with the permission 'edit articles'

I've never used Entrust before, but I looked through the code on GitHub.
Permission has a belongsToMany for roles.
Role has a belongsToMany for users.
Therefore you should be able to chain the commands like so:
$permission = Permission::find(1);
$users = $permission->roles()->users;
If you are planning on chaining relationships, you should add braces onto the relationship name.

Thanks to ntzm, I was able to figure out how to find all the users who have access to the Permission. Not sure if this will help anyone.
There are two different types of employees who has access to a permission. One from the roles and second is where the permission is given direction to them. I haven't used the direct one yet, but I do have roles that have access to permissions. Here's how I was able to get the users with a certain permission:
$permission = Permission::findByName('edit posts');
$employees = [];
//Loop through each role.
foreach($permission->roles as $r){
$emps = $r->users;
//Cycle through the users.
foreach($emps as $e){
$employees[] = $e;
}
}
return $employees;
Hopefully this helped someone who also needed this. :)

Related

How to remove any role by using removeRole() in laravel?

I have three models user,roles,model_has_roles,when i assign any role to the user from the roles table it's creating an instance of the model in model_has_roles table.I am using removeRole() laravel method for removing roles ,i am giving some details what are the roles present inside my database like(super-market,notification,all...).it's deleteing all roles except notification,all.
$roleName = implode(' ,',$roleName); // "super-market" or "all"
foreach ($roles->pluck('name')->toArray() as $roleName) {
$user->removeRole($roleName);
}
Now what i need is irrespective of the role(any role) i want to delete that role ,some of the roles it's deleteing and remove the instance of the model from the model_has_roles and some of the roles are not deleted (for example all,notification),please help me to fix this issue
there is no built-in laravel package for managing roles and permission and removeRole() is not in laravel (I dont know why you did wrote removeRole laravel method ), there is a package called laravel-permission that has the same table design of yours. if you are using this package you can find docs in here. if you are writing your own try debugging it with dd() and tinker to find out what's wrong with some that they won't be deleted.
I got it reverse in first place, you must use explode instead, and move first line into foreach loop
foreach ($roles->pluck('name')->toArray() as $roleName) {
$roleName = explode(',',$roleName);
$user->removeRole($roleName);
}

Laravel - Refactoring User Permission "Gate::Define" Code Into Easier to Read Code

So what i'm basically trying to do is refactor my long bit of code to something more simpler. I found this snippet of code at this website and I don't really understand what's going on inside the code. I don't think that this snippet of code will work considering I am using different policies and methods then what's standard.
Code Snippet From Site:
//PermissionsServiceProvider.php
public function boot()
{
Permission::get()->map(function($permission){
Gate::define($permission->slug, function($user) use ($permission){
return $user->hasPermissionTo($permission);
});
});
}
Can someone please explain what exactly is going on in this bit of code?
My Code:
// Posts Policy
Gate::define('post.view', 'App\Policies\Blog\PostsPolicy#view');
Gate::define('post.create', 'App\Policies\Blog\PostsPolicy#create');
Gate::define('post.update', 'App\Policies\Blog\PostsPolicy#update');
Gate::define('post.delete', 'App\Policies\Blog\PostsPolicy#delete');
Gate::define('post.publish', 'App\Policies\Blog\PostsPolicy#publish');
Gate::define('post.edit', 'App\Policies\Blog\PostsPolicy#edit');
Gate::define('post.global', 'App\Policies\Blog\PostsPolicy#global');
// Categories Policy
Gate::define('category.view', 'App\Policies\Blog\CategoriesPolicy#view');
Gate::define('category.create', 'App\Policies\Blog\CategoriesPolicy#create');
Gate::define('category.update', 'App\Policies\Blog\CategoriesPolicy#update');
Gate::define('category.delete', 'App\Policies\Blog\CategoriesPolicy#delete');
Gate::define('category.edit', 'App\Policies\Blog\CategoriesPolicy#edit');
Gate::define('category.global', 'App\Policies\Blog\CategoriesPolicy#global');
// Tags Policy
Gate::define('tag.view', 'App\Policies\Blog\TagsPolicy#view');
Gate::define('tag.create', 'App\Policies\Blog\TagsPolicy#create');
Gate::define('tag.update', 'App\Policies\Blog\TagsPolicy#update');
Gate::define('tag.delete', 'App\Policies\Blog\TagsPolicy#delete');
Gate::define('tag.edit', 'App\Policies\Blog\TagsPolicy#edit');
Gate::define('tag.global', 'App\Policies\Blog\TagsPolicy#global');
// Parts Section Policy
Gate::define('part.section.view', 'App\Policies\Parts\PartSectionsPolicy#view');
Gate::define('part.section.create', 'App\Policies\Parts\PartSectionsPolicy#create');
Gate::define('part.section.update', 'App\Policies\Parts\PartSectionsPolicy#update');
Gate::define('part.section.delete', 'App\Policies\Parts\PartSectionsPolicy#delete');
Gate::define('part.section.edit', 'App\Policies\Parts\PartSectionsPolicy#edit');
Gate::define('part.section.global', 'App\Policies\Parts\PartSectionsPolicy#global');
// Parts Policy
Gate::define('part.view', 'App\Policies\Parts\PartsPolicy#view');
Gate::define('part.create', 'App\Policies\Parts\PartsPolicy#create');
Gate::define('part.update', 'App\Policies\Parts\PartsPolicy#update');
Gate::define('part.delete', 'App\Policies\Parts\PartsPolicy#delete');
Gate::define('part.edit', 'App\Policies\Parts\PartsPolicy#edit');
Gate::define('part.global', 'App\Policies\Parts\PartsPolicy#global');
// Admin Management Policy
Gate::define('admin.global', 'App\Policies\AdminManagementPolicy#global');
// User Management Policy
Gate::define('user.global', 'App\Policies\UserManagementPolicy#global');
Is there a way to do this as a foreach loop from my permissions table? Here's some Pseudo code:
foreach($permissions as $permission) {
Gate::define($permission->slug, 'App\Policies\' . $permission->category . 'Policy#' . $permission->name);
}
Question: Any way to make my code more compact and easier to read like the code snippet from the website?
First of all, the author of that article did not use policies at all, he created a permissions table and then bound the permissions he created to laravel gates by the code snippet
Permission::get()->map(function($permission){
Gate::define($permission->slug, function($user) use ($permission){
return $user->hasPermissionTo($permission);
});
});
Let's break it line by line
Permission::get() // Query all permissions defined in permissions database table
->map(function($permission){ // Foreach permission do the following
Gate::define($permission->slug, // Create new gate with the permission slug
function($user) use ($permission){
return $user->hasPermissionTo($permission); // the user table has many to many relation with permissions table, here we only check if $user is associated with $permission
});
});
To make your code more dynamic, I suggest you to do the following:
Database structure
Create permission database table
Create roles database table
Create permission_role pivot database table
Create role_user pivot database table
Define Relationships
Role has many permissions ( many to many relationship, define it with belongsToMany )
Permission belongs to many roles ( many to many relationship, define it with belongsToMany )
User has many roles ( many to many relationship, define it with belongsToMany )
Reduce the number of global permissions
By utilising Gate::before you can allow specific user who has global or root permission to authorise all defined abilities:
Gate::before(function ($user, $ability) {
if ($user->hasPermission('root-access')) {
return true;
}
});
If you implement the database permissions you no longer need to create policies for every model, and the gates will be defined using the above code dynamically.
Personally, your existing code is fine. It works. It is readable. While it might become more verbose as your app grows, it also might not. So why improve it?
That said, here are some ideas. Most of your code is a mapping between permission and policy implementation. For example 'part.view' maps to 'App\Policies\Parts\PartsPolicy#view. The "weight" of this mapping can't be removed: it can only be moved.
You might consider moving it to a simpler configuration file, something that looks like this:
// config/permission-map.php
<?php return [
'post.view' => 'App\Policies\Blog\PostsPolicy#view',
'post.create' => 'App\Policies\Blog\PostsPolicy#create',
'post.update' => 'App\Policies\Blog\PostsPolicy#update',
'post.delete' => 'App\Policies\Blog\PostsPolicy#delete',
// etc...
];
Then in your boot you read that config and iterate:
// boot permissions
$permission_map = require_once('config/permission_map.php');
foreach ($permission_map as $permission => $policy_implementation) {
Gate::define($permission, $policy_implementation);
}
Advantage: adding a new policy mapping only changes the most salient information, and you don't have to think about how to make that mapping happen - today that is Gate::define but tomorrow maybe it's Sentry::policy. Additionally, by separating data from the code, you can test the code more freely.
Another approach could be annotations: in the DocBlock of your policy implementation, you write your own annotation syntax, which you then parse and compile into the configuration file. Along the lines of
namespace App\Policies\Blog;
class PostsPolicy {
/**
* #permission post.view
*/
public function view() { /* ... */ }
}
I, personally, am not a fan of this: it adds a layer of inner framework whose value I find it hard to measure.

Algorithm that gets latest inputs in database based on two different factors

I have a website build upon laravel. The website consist of users, and users can follow each other. Users can make Shoutouts (like a tweet), and the users that are following each other should be able to see these. I have a User table in my database, and a Shoutout table, and a Follow table.
As it is made i Laravel, the User has a hasMany relationship to both the Shoutout and the Follow table.
So when a user logs in, I want to get all the people that the User is following. This i do by the following:
$following = Follow::whereUser_id($user->id)->get();
However, how would I now get the Shoutouts from the users in $following, in an order descending from the time the shoutout was created, so I can do a foreach($shoutouts as $shoutout) in my view?
The ideas is that the User can see the latest Shoutouts from the people that the user is following.
If i did something like:
$following = Follow::whereUser_id($user->id)->get();
foreach($following as $follow) {
$shoutouts = $shoutouts . Shoutout::whereUser_id($follow->user_id)->get();
}
I would get them in an incorrect order, as this would give me all the shoutouts of a specific user right after each other, but I would like to get them in descending order, so the user sees the latest shoutouts first.
All help appreciated.
You can try it by using join as:
Assuming you have a followed_user_id in your Follow table.
$shoutouts = Shoutout::join('follow', 'shoutout.user_id', '=', 'follow.followed_user_id')
->where('follow.user_id', $user->id)
->select(''shoutout.*'')
->orderBy('shoutout.created_at', 'desc')
->get()
You're looking for https://laravel.com/docs/5.3/eloquent-relationships#eager-loading on your followed user's shoutouts. If you have your relationships defined correctly you should be able to do:
$following = Follow::whereUser_id($user->id)->with('shoutouts')->get();
Then access the shoutouts by user with:
foreach($following as $follow) {
$shoutouts = $follow->shoutouts;
//Do Something With The Collection Of Shoutouts
}
UPDATE
To get just the shoutouts of users they follow you would define a hasManyThrough on your user table:
public function followerShoutouts()
{
return $this->hasManyThrough(Shoutout::class, Follow::class, 'user_id', 'user_id_being_followed');
}
Then you can do:
$shoutouts = User::with(['followerShoutouts' => function($query) {
return $query->orderBy('created_at', 'desc');
}])->find($userId);

How to chain eloquent relations in laravel?

So far I was extracting the relation objects as arrays and then doing something like:
App\Model::find($id)
But however is there a way to do something like:
Auth::user()->group()->members()
It works until Auth::user()->group but no further chaining. Please help if you've done something. Or I'm just newbie.
You could use eager loading to load the user's group and then load all of the members of that group.
$user = User::with(['group', 'group.members'])->find(1);
// OR if you already have a user object (Like when using the Auth facade)
$user = Auth::user()->load(['group', 'group.members']);
foreach ($user->group->members as $member) {
// Do something with a member
}
However, if you essentially want to jump down the structure a level, and get all the members related to a user, you could use the hasManyThrough relationship, in that a user has many members, through a group.
// In your User model
public function members()
{
return $this->hasManyThrough(Member::class, Group::class);
}
That way you can simply access the members directly through the user:
$members = Auth::user()->members;
Instead of doing a query to access the user's group and then doing another query to access that group's members, Laravel would use a single query with a join to get you the members.
Take a look at the hasManyThrough relationship here
Try this
Auth::user()->group->members

How to get user role in Yii2?

How to get user role in Yii2?
I searched and read Yii2 guide but I didn't find any solution.
You can get Roles for an user by using getRolesByUser function
You can use it like this
\Yii::$app->authManager->getRolesByUser($user_id);
You can use:
Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());
I use :
if (\Yii::$app->authManager-> getAssignment($role,$rule_id))
for filtering user id and role in rbac, More details on Yii2 Documentation
One more example how to get user role:
Yii::$app->getUser()->identity->role;
It works if you have column with name "role" in your user table.
You can use :
$user =[];
$userAssigned = Yii::$app->authManager->getAssignments(user_id);
foreach($userAssigned as $userAssign){
$user[] = $userAssign->roleName;
}
If you're using amnah/yii2-user module, you can use this:
Yii::$app->user->identity->role->name
It will give you the current user role name
The good and more visual decision will be setting constants of all roles.
$userID = $user->getId();
array_keys(Yii::$app->authManager->getRolesByUser($userID))[0] == User::ROLE_NAME
You can get role of the user by using createcommand.
$roleModel = Yii::$app->db
->createCommand("Select * from auth_assignment where user_id='889'")
->queryOne();
echo $roleModel['item_name'];
This will you user's role in auth assignment. Now you can check that if user is admin or editor or member.

Categories