specific form field editable based on User Role

Well, I can restrict users access permissions(i.e. view, create, update or delete) to forms or views based on access control using behaviors.

But I wonder how I can restrict a specific user from editing some of the fields in the form i.e. allow specific fields is read-only for some users and editable by some users.

Can I provide any kind of access rule in the model or attach some rule in the _form.php itself.

Thanks.

Hi there - is it possible? not possible!

Thanks.

As a rule of thumb: If it’s possible in PHP then it’s possible in Yii.

As far as I know, the framework core doesn’t provide any built in mechanism for that. You have to check user’s permissions in the form and add “disabled” attribute dinamically.




$form->field(/*...*/)->textInput(['disabled' => !\Yii::$app->user->can('editFormField')]);



Also, you have to check the permissions in the model and declare attribute as safe or unsafe dinamically. Implementation may vary, depending on the usage of scenarios.

Thank you very much phtamas. Your suggestion is working perfectly.

Don’t forget to edit the rules in your model class !

Users can edit the HTML and edit the inputs.

So you have to make some attributes "safe" and other attributes "unsafe".

Something like this :




public function rules()

{

  return [

    //All users can edit "name" and "description"

    [['name', 'description'], 'safe'],

    //Only certain users can edit "role"

    [['role'], \Yii::$app->user->can('editFormField') ? 'safe' : 'unsafe'],

    ...

  ];

}



Hi Timmy78 - I have tried to implement your suggestion in model rules - but then I am getting the error like

ReflectionException


Class unsafe does not exist

with the below line highlighted.


$reflection = new ReflectionClass($class);

Thanks.

Or try like this :




public function rules()

{

  return [

    //All users can edit "name" and "description"

    [['name', 'description'], 'safe'],

    //Only certain users can edit "role"

    [['role'], 'safe', 'when' => function($model) { 

        return  \Yii::$app->user->can('editFormField');

      }],

    ...

  ];

}



Hi Timmy78 - Tried, but it doesn’t fail on any user - for testing purpose I have used this code


[['age'], 'safe', 'when' => function($model) { 

                return  \Yii::$app->user->can('admin');

              }],

but validation doesn’t fail and I am able to insert in the age field even when logged in with user-id other than admin.

Mmmhh I don’t know.

The other way is to use scenarios ^^




//Action:

if(Yii::$app->user->can('admin'))

  $model->scenario = 'admin';


//Model

[['age'], 'safe', 'on' => 'admin']



Hi Timmy78




//Action:

if(Yii::$app->user->can('admin'))

  $model->scenario = 'admin';



where exactly I should put this code, I have tried to add this in actionCreate() with no effect.

Thanks.

Yes you have to put this code in the actions create and update.

Thank You - But I am able to insert in to the field even with the guest role, without any problem.

my code in model is like:


[['age', 'district_city', 'state', 'pin_code'], 'integer'],

[['age'], 'safe', 'on' => 'admin'],

and in the controller say actionCreate is like:




public function actionCreate()

    {

        $model = new PatientEntry(); 


        if ($model->load(Yii::$app->request->post()) && $model->save()) {

        //Action:

        if(Yii::$app->user->can('admin'))

          $model->scenario = 'admin';

            return $this->redirect(['view', 'id' => $model->id]);

        } else {

            return $this->render('create', [

                'model' => $model,

            ]);

        }

    }



Yes because you put "age" in the rule integer". So the attribute become safe in all cases

Thanks Timmy78 You have spotted the problem correctly. Now If I remove the "age" from the integer rule, the data is not getting inserted in that field.

Thank you so much once again.

However I have to make a little modification i.e. put the suggested code before the line "if ($model->load(Yii::$app->request->post()) && $model->save())" like




public function actionCreate()

    {

        $model = new PatientEntry();

        if(Yii::$app->user->can('admin'))

            $model->scenario = 'admin';  

       

        if ($model->load(Yii::$app->request->post()) && $model->save()) {

                  

            return $this->redirect(['view', 'id' => $model->id]);

        } else {

            return $this->render('create', [

                'model' => $model,

            ]);

        }

    }



I’m afraid “safe” rule has a different purpose.