可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am working on yii2
. I have some user roles
. Admin has all the level of access. Other users have a low level of access. There is a user list which is visible to the other user. In this list all of the details of the users in the system is available. Now, I want to hide some user information from other users. The roles I want to hide are 1,6,7,8
and the role of which I want to hide is 5
. Other than the mentioned user roles should be visible to 5
. For this, I have updated the index controller.
$searchModel = new UserSearch();
$queryParams=Yii::$app->request->queryParams;
//check if user or one of the managers
$isAdmin=in_array(Yii::$app->user->identity->user_role,[1]);
//set params if normal user
if(!$isAdmin){
$queryParams['UserSearch']['user_role']=in_array(Yii::$app->user->identity->user_role,[2,3,4,5]);
}
$dataProvider = $searchModel->search($queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]);
Now on running my project, I am only seeing the admin user. In $queryParams['UserSearch']['user_role']=
I have tried to pass the single value of user role 5
and it does shows me only 5
role users. But I want to show the users with role 2,3,4,5
.
Update 1
My search model
class UserSearch extends User
{
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id','group_id'], 'integer'],
[['email','username', 'name','contact_number','group_id','user_role'], 'safe'],
];
}
/**
* @inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$query = User::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'status' => $this->status,
]);
$query->andFilterWhere(['like', 'id', $this->id])
->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'username', $this->username])
->andFilterWhere(['like', 'email', $this->email])
->andFilterWhere(['like', 'contact_number', $this->contact_number])
->andFilterWhere(['=', 'user_role', $this->user_role])
->andFilterWhere(['=', 'group_id', $this->group_id]);
// $query->andFilterWhere(['=','user_type','user']);
if(Yii::$app->user->identity->user_role == Roles::ROLE_TEAM_LEAD && Yii::$app->user->identity->group_id != ''){
$query->andFilterWhere(['=','group_id', Yii::$app->user->identity->group_id])->andWhere('user_role=4');
}
//$query->andFilterWhere(['!=', 'id', Yii::$app->user->id]);
return $dataProvider;
}
}
Any help would be highly appreciated.
回答1:
Change your line
$queryParams['UserSearch']['user_role']=in_array(Yii::$app->user->identity->user_role,[2,3,4,5]);
to
$queryParams['UserSearch']['user_role']=in_array(Yii::$app->user->identity->user_role,[2,3,4,5])?[1,6,7,8]:'';
and inside your search model change the condition
->andFilterWhere(['=', 'user_role', $this->user_role])
to
->andFilterWhere(['NOT IN', 'user_role', $this->user_role])
so your search()
method will look like
public function search( $params ) {
$query = User::find ();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider ( [
'query' => $query ,
] );
$this->load ( $params );
if ( !$this->validate () ) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere ( [
'id' => $this->id ,
'status' => $this->status ,
] );
$query->andFilterWhere ( [ 'like' , 'id' , $this->id ] )
->andFilterWhere ( [ 'like' , 'name' , $this->name ] )
->andFilterWhere ( [ 'like' , 'username' , $this->username ] )
->andFilterWhere ( [ 'like' , 'email' , $this->email ] )
->andFilterWhere ( [ 'like' , 'contact_number' , $this->contact_number ] )
->andFilterWhere ( [ 'NOT IN' , 'user_role' , $this->user_role ] )
->andFilterWhere ( [ '=' , 'group_id' , $this->group_id ] );
// $query->andFilterWhere(['=','user_type','user']);
if ( Yii::$app->user->identity->user_role == Roles::ROLE_TEAM_LEAD && Yii::$app->user->identity->group_id != '' ) {
$query->andFilterWhere ( [ '=' , 'group_id' , Yii::$app->user->identity->group_id ] )->andWhere ( 'user_role=4' );
}
//$query->andFilterWhere(['!=', 'id', Yii::$app->user->id]);
return $dataProvider;
}
回答2:
If all searched model items should hide/show secure information, you can add second option to search()
function that will show hide secure info on query building. For example:
$searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams,
Yii::$app->user->identity->user_role === User::ADMIN_ROLE);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
or you can add query condition at controller:
$searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if(Yii::$app->user->identity->user_role === User::ADMIN_ROLE) {
$dataProvider->query->andWhere(/* come condition*/);
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
If your project will use access-control at other code places, highly recommend to use Role Based Access Control (RBAC) that included at default Yii2 configuration. Using this future, you simply can check user permissions without additional columns at user
table. It might look like this:
$searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if(Yii::$app->user->can(Roles::USER_VIEW_PRIVATE_INFO)) {
$dataProvider->query->andWhere(/* come condition*/);
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
回答3:
Why you are changing the index
view by using your controller? As i can see that in your search class there is already a check of user role
.
if(Yii::$app->user->identity->user_role == Roles::ROLE_TEAM_LEAD && Yii::$app->user->identity->group_id != ''){
$query->andFilterWhere(['=','group_id', Yii::$app->user->identity->group_id])->andWhere('user_role=4');
}
After this you can add
if(Yii::$app->user->identity->user_role == Roles::ROLE_INVENTORY_MANAGEMENT && Yii::$app->user->identity->group_id =='')
{
$query->andFilterWhere(['=','group_id', Yii::$app->user->identity->group_id])->andWhere('user_role IN (2,3,4,5)');
}
So your final code would be like this
if(Yii::$app->user->identity->user_role == Roles::ROLE_TEAM_LEAD && Yii::$app->user->identity->group_id != ''){
$query->andFilterWhere(['=','group_id', Yii::$app->user->identity->group_id])->andWhere('user_role=4');
}
else if(Yii::$app->user->identity->user_role == Roles::ROLE_INVENTORY_MANAGEMENT && Yii::$app->user->identity->group_id =='')
{
$query->andFilterWhere(['=','group_id', Yii::$app->user->identity->group_id])->andWhere('user_role IN (2,3,4,5)');
}
I hope this also works with your filters :)