0

I have two levels of admins who can create and update users, "Admin" and "Manager".

In my User _form.php I have a "user_type" dropdown that has my account levels.

I want to limit managers from creating "Admin" accounts, and obviously hide the dropdown entirely when a user is updating their own record.

a) Is there a way to use rules() to control this behaviour? b) I thought about creating a scope called "hideAdmin" which would look like this:

'hideAdmin' => array(
   'condition' => 'user_type != "Admin"',
),

and then creating a public method in my model called "scopeToUse()" which looks like this:

    public function scopeToUse() {
        $scope = 'hideAdmin()';
        if(Yii::app()->authManager->checkAccess('Admin', Yii::app()->user->id)) {
            $scope = 'orderAsc()';
        } 
        return $scope;
    }

And finally, creating my dropdown list like this.

<?php echo $form->dropDownList($model,'user_type_id',
   CHtml::listData(UserType::model()->scopeToUse()->findAll(),'id','user_type')); ?>

I was hoping 'scopeToUse()' would return the scope name and it would work, but I just end up getting this back:

Fatal error: Call to a member function findAll() on a non-object

Any idea on the right way to do this?

EDIT

I ended up taking a cue from @Rafay-Zia-Mir and creating a new method in my user class that checked permissions and returned the appropriate CHtml::listData along with the scope I wanted. Wasn't exactly what I had intended, but the end result is the same, it kept me from putting too much code in my view, and it allowed me to use my scopes instead of duplicating the selection criteria.

This was the code:

    public function userTypeDropdown() {
        if(Yii::app()->authManager->checkAccess('Admin',Yii::app()->user->id)) {
            $listData = CHtml::listData(UserType::model()->findAll(),'id','user_type');
        } else {
            $listData = CHtml::listData(UserType::model()->hideAdmin()->findAll(),'id','user_type');
        };
        return $listData;
    }
McB
  • 1,082
  • 1
  • 18
  • 36
  • obviously scopeToUse() is not an object thats why you are getting this error. – Rafay Zia Mir Mar 03 '14 at 19:17
  • findAll is a method of CActiveRecord base class but you are calling it for a function – Rafay Zia Mir Mar 03 '14 at 19:22
  • Right, I'm just not sure how to get it to work. If I do UserType::model()->hideAdmin()->findAll... it works. So how do I just pipe in the right scope? – McB Mar 03 '14 at 19:23
  • actually i cant understand your question. Do you want to show the items in dropDown based upon the role of the current user? If current user is not admin then hide the dropDown? is that what you want? – Rafay Zia Mir Mar 03 '14 at 19:39
  • Yes exactly. So I created 2 scopes to handle that, and a method in the UserType model. I just want that method to return the appropriate scope name, ideally through a variable rather than multiple returns (return UserType::model()->hideAdmin() works, where hideAdmin() is the name of the scope). – McB Mar 03 '14 at 19:42

1 Answers1

0

Ok actually you can do this by using If statement in your View code. You can do like this

<?php 
          if(Yii::app()->authManager->checkAccess('Admin', Yii::app()->user->id)) {
         ?>
         <?php $criteria=new CDbCriteria();
             $criteria->condition="NOT user_type=Admin";
                echo $form->dropDownList($model,'user_type_id',
                    CHtml::listData(UserType::model()->findAll($criteria),'id','user_type')); ?>

         <?php } ?>

If the user is admin only then the dropdown will be shown.
EDIT: If you want to get it using function call then you can use this.

public function scopeToUse() {
        if(Yii::app()->authManager->checkAccess('Admin', Yii::app()->user->id)) {
            $this->getDbCriteria()->mergeWith(array(
        'condition' => 'NOT user_type="Admin"',
         'order'=>'id ASC'
    ));

        } 
        return $this;
    }

then you can use use

<?php  echo $form->dropDownList($model,'user_type_id',
                        CHtml::listData(UserType::model()->scopeToUse()->findAll(),'id','user_type')); ?>
Rafay Zia Mir
  • 2,116
  • 6
  • 23
  • 49
  • Thanks for this. It is what I'll put into my view to hide the dropdown from regular users who use the form to update email and password, however I want to filter the dropdown so that 'Managers' can't assign anyone as 'Admin'. 'Admin' is sort of a super user in my app. – McB Mar 03 '14 at 20:06
  • ok then on what criteria do you want to filter the droprDown? "Managers cant assign anyone as Admin" who is anyone? and who is the right user for admin privileges? – Rafay Zia Mir Mar 03 '14 at 20:11
  • Just what is in the scope defined above. 'hideAdmin' => array( 'condition' => 'user_type != "Admin"', ), – McB Mar 03 '14 at 20:13
  • @McB, tell me what are the attributes of UserType? I am asking because UserType::model()->findAll() will return all the records in table. Do you want that records in dropDown having user_type other than admin? – Rafay Zia Mir Mar 03 '14 at 20:26
  • I know I can do it with criteria, or by putting in 2 line of dropdown code (one IF Admin, another IF Manager). I'm just trying to figure out if there is a way to use my already created scopes instead of a new CDbCriteria object. – McB Mar 03 '14 at 21:03
  • Thanks @Rafay. I was hoping to find a way to use the actual scopes I created rather than making them again (just for ease of updating). I ended up going with what I put in my post. – McB Mar 04 '14 at 16:41