Yii. Get Users based on role - yii

I am using native CDbAuthManager to implement RBAC in my webapp. How can I get all the users who has permission to do a role? Suppose I have role named updateprofile. I want to get all the users assigned to that role. I searched the documentation and couldnt find a function.
(I know i can iterate through all user models and do a checkAccess() in a foreach loop, but I prefer a nicer solution )

The easiest way I've found to do this is to create an AuthAssignment model that maps to your auth_assignment table. Then, you can setup relationships, scopes, etc for it and query using it to retrieve all user models. There isn't anything particularly special about the auth_assignment table (as it is mainly just roles in there).

code like
class AuthAssginment extends CActiveRecord{.....
public function getUsersBaseOnRole($role) {
return Yii::app()->db->createCommand()
->select('userid')
->from($this->tableName())
->where('itemname=:role', array(
':role' => $role,))
->queryAll() ;
}....

I think the other replies do not give you the perfect result because roles can be hierarchical and so, you cannot use direct queries or relations. My solution which works well is:
// list all users with 'userManagement' role
if($users = Users::model()->findAll()) {
foreach($users as $id => $user) {
if(!$user->checkAccess('userManagement')) {
unset($users[$id]);
}
}
$users = array_values($users); // to reset indices (optional)
}

Related

Laravel query parameters or pretty parameters for api

i am willing to know which is the best practice to use parameters for developing an api
//url
http://localhost:8000/api/my_orders/1/10/1
//route
Route::get('/my_orders/{user_id}/{limit}/{page}', 'ApiControllers\OrderController#getOrdersByUser');
//method
public function getOrdersByUser($user_id, $limit, $page)
{
//logic using $user_id, $limit, $page
}
or
//url
http://localhost:8000/api/my_orders?user_id=1&&limit=5&&page=1
//route
Route::get('/my_orders', 'ApiControllers\OrderController#getOrdersByUser');
//method
public function getOrdersByUser(Request $request)
{
//logic using $request->user_id, $request->limit, $request->page
}
this api is for mobile applications and for front end Vue application
thank you
Laravel has pagination built in, it will check for page and perpage query string arguments using paginate() or something that uses Paginator related methods for fetching a subset of your data.
So when you have ?page=1&perpage=20 and you use paginators, they will pick these up automatically.
For REST API endpoints, try and make the urls as descriptive as possible and based on your models.
// get a list of orders
GET /api/orders
// get a list of orders belonging to user 1
GET /api/orders?user_id=1
// get a paginated list of 20 orders belonging to user 1
GET /api/orders?user_id=1&page=1&perpage=20
You are calling your endpoint my_orders, which basically says it will return orders owned by the authenticated user. So, in my opinion, it wouldn't make sense here to include a user_id argument.
// get a list of orders owned by the authenticated user
GET /api/my_orders
You can use my_orders, but more descriptive will be to use a url like:
// get a list of orders owned by user
GET /api/users/{user_id}/orders
Edit:
In your case, you probably want to create a UserOrderController
public function index($user_id)
{
// first fetch user, if fetch fails show error
$user = User::findOrFail($user_id);
// maybe add some code here to check if the authenticated user is allowed to view this user's orders
// return paginated orders
return $user->orders()->paginate();
}
And you would need to define the relations in the models:
App/User.php
public function orders()
{
// assuming orders table has a column user_id
return $this->hasMany(Order::class);
}
App/Order.php
// inverse relation
public function user()
{
return $this->belongsTo(User::class);
}
I use 1st way for only those parameters which are associated with DB, like user_id here, because it reduces 1 step for me to get the specific data from DB of that particular ID. for more dynamic url laravel will go to this route even when you supply the wrong values and you have to apply the regix to avoid that.
Secondly, URLs like 2/20/4 wouldnt make any sense and hard to understand. So the best way in my opinion is the second way.

Eloquent: Get pages based on user role

I have a User, Role & Page setup, all with many-to-many relationships and the pivot tables setup in the usual fashion (role_user, page_role), along with the eloquent methods to attach a model to the pivot tables.
My idea is to allow a user to have many roles, and a page can be accessed by many roles.
However now I'd like to return a collection where I have my users details and then the pages they're allowed to access.
The closest I have got is:
return User::find( Auth::user()->id )->with('roles.pages')->first()->roles;
Now this returns each role the user has, and each page that the role can access. Which is correct, however I have duplication on the pages part.
How would I go about getting only a list of pages the user is able to access with no duplication?
Cheers
Read that answer to get you on the track: HasManyThrough with one-to-many relationship
Only for your setup you need to adjust the query - join 2 pivot tables (and make sure they represent real data, ie no rows referencing non-existing models):
// User model
// accessor so you can access it like any relation: $user->pages;
public function getPagesAttribute()
{
if ( ! array_key_exists('pages', $this->relations)) $this->loadPages();
return $this->getRelation('pages');
}
// here you load the pages and set the collection as a relation
protected function loadPages()
{
$pages = Page::join('page_role as pr', 'pr.page_id', '=', 'pages.id')
->join('role_user as ru', 'ru.role_id', '=', 'pr.role_id')
->where('ru.user_id', $this->id)
->distinct()
->get(['pages.*', 'user_id']);
$hasMany = new Illuminate\Database\Eloquent\Relations\HasMany(Page::query(), $this, 'user_id', 'id');
$hasMany->matchMany(array($this), $pages, 'pages');
return $this;
}
One more thing: I hardcoded tables and columns names for sake of simplicity, but in real life I suggest you rely on the relationships and their getters, like: $relation->getTable(), $relation->getForeignKey() etc.
Now suggestion about your code:
return User::find( // 2. query to get the same user
Auth::user()->id // 1. query to get the user and his id
)->with('roles.pages')
->first() // 3. query to get ANOTHER user (or the same, luckily..)
->roles;
Use Auth::id() instead of Auth::user()->id (for Laravel ver 4.1.25+) to avoid redundant query
find() and first() are methods that execute the query, so you just returned the user with id = Auth::user()->id and moment later you fetch another one, who comes first() from the users table..
You don't need to use User::whatever for authenticated user, use Auth::user() instead.
So the code with suggested solution would look like this:
Auth::user()->pages; // collection of Page models with unique entries

Eloquent many-to-many with filters on both sides

I've been reading the docs but I"m not sure how to do this. http://doc.laravelbook.com/eloquent/#many-to-many
Say I have a users, roles, and a pivot table.
I have belongsToMany set up for both Role and User
In a controller, I want to get a user_id and return what roles they have of a specific type only.
(There is also a role type table, but I can work with the IDs directly).
I start something like this
$specific_type_role = Role::where('role_type_id', 3)::where(?$user_id?)
//need to involve
$circle_users = RoleUser::where('user_id', $user_id)->get();
but I think it should be able to be done automatically. don't know how to include the filter right in the query.
Not sure if it's that what you need but, you probably will be able to do something like that:
public function getAdminRoles()
{
$user = User::find(1);
return $user->roles()->where('role_type_id', 1)->get();
}

Adding more info to Laravel's auth user

I am new to Laravel and I am trying to add some more information to the user variable I am getting back from Auth::user()
To be more detailed, I have a Many-to-Many relationship to a "Privileges" table. As the name suggests, that table holds specific privileges a user can have. In the pivot table, I just hold the the user_id and privilege_id. I have the necessary models set up and everything works fine if I do this in my before filter:
$user = Auth::user();
$user->priviledges()->get();
Now, I would really like to avoid querying every single time I want to find the privileges and would like to have Laravel's Auth class include the privilege information, so that when I do
$user = Auth::user();
I can do a
$user->privileges;
to get an array of all privileges the user has.
Any suggestions for the best approach?
The link to the answer above is not working. However, I found another solution here which worked for me as follows:
First I created a model called EmailPref.php in my own case;
app/model/EmailPref.php
class EmailPref extends Eloquent {
protected $table = 'email_pref';
public function user()
{
return $this->belongsTo('User');
}
}
and then I created a relationship (in my own case) in the User model like so;
app/model/User.php
public function emailPref()
{
return $this->hasOne('EmailPref');
}
I subsequently referenced it anywhere required within my application like so:
Auth::user()->emailPref;
Hence, I was able to add more information to the Auth user.
I'm no Laravel pro, but i think this will solve your problem: http://forums.laravel.io/viewtopic.php?id=1652

Drupal 6, Views 2: Is it possible to have a filter that only applies to registered users?

Is it possible to create a filter in a Drupal 6 View that is only applied for registered users?
For one filter I need I'm using the user vote (With fivestar and votingapi) to know if they user already voted this node or not, and when the user is annonymous, is working as if all the votes from all the annonymous users where from the same. This is why I need to add this filter, but ignore it in case the user is annonymous.
Thanks a lot in advance for the help!
If you're comfortable with php, download the Views PHP Filter module (http://drupal.org/project/viewsphpfilter). This module allows you to easily write your own custom filters for any view.
After downloading and enabling the module, create a new view and add a "Node: Node ID PHP handler" filter. Now you can add custom php code for any filter you want. Perhaps something like:
global $user;
$allowed = array('authenticated user');
foreach ($user->role as $role) {
if (in_array($role, $allowed)) {
$nids = //Run custom filter query for allowed users
}
else {
$nids = //Run alternate filter query for anonymous users
}
}
return $nids;
The code should return a list of node ids to display.