How to hide admin account from other users

2019-05-23 04:10发布

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.

3条回答
倾城 Initia
2楼-- · 2019-05-23 04:12

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楼-- · 2019-05-23 04:23

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;
}
查看更多
老娘就宠你
4楼-- · 2019-05-23 04:39

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 :)

查看更多
登录 后发表回答