Authmanager And Menu Visibility

Dear Friends

If you have numerous menu items and if you have classified users with some roles or types,

authManager can help us to hide or display a menu item depending upon type of the user logged in.

Let us look at an implementation with minimal set of roles and menu items.

We have following roles assigned to user.

1.registered.

2.admin.

We have following menu items:

1.Home.

2.About.

3.Contact.

4.Login.

5.Logout.

6.Posts.

7.PostsAdmin.

We have to acheive the following visibility.

unregistred guests:Home,About,Login.

registered:Home,about,Contact,Posts,Logout.

admin:Home,about,Contact,Posts,PostAdmin,Logout.

Now we have to load the authorization logic to all the controllers.

For that we have infuse the logic in parent class Controller in Components folder.

components/Controller.php




public $auth;

	

protected function loadAuth()

{

	$auth=new CPhpAuthManager;


//we are creating a default role sothat every one including anonymous will get the role.

	$auth->defaultRoles=array('global');


//we are creating items in the name of every menu item.

	$auth->createOperation('home');

	$auth->createOperation('about');

	$auth->createOperation('contact');

	$auth->createOperation('posts');

	$auth->createOperation('postsAdmin');

	$auth->createOperation('login','login','return Yii::app()->user->isGuest;');//declaring a business rule.

	$auth->createOperation('logout');


//creating default role 'global'		

	$global=$auth->createRole('global');

	$global->addChild('home');

	$global->addChild('about');

	$global->addChild('login');


//creating role 'registered' and adding child 'global'		

	$reg=$auth->createRole('registered');

	$reg->addChild('contact');

	$reg->addChild('global');

	$reg->addChild('posts');

	$reg->addChild('logout');


//creating role 'admin' and adding children 'global' and 'registered'		

	$admin=$auth->createRole('admin');

	$admin->addChild('registered');

	$admin->addChild('postsAdmin');

	

//assigning roles 	

	if(!Yii::app()->user->isGuest)

		$auth->assign(Yii::app()->user->role,Yii::app()->user->id);

	return $this->auth=$auth;

		

}

	

public function init()

{

	$this->loadAuth();

}



In main layout file you can declare the menu item like below.




$this->widget('zii.widgets.CMenu',array(

	'items'=>array(

			

		array('label'=>'Home', 'url'=>array('/site/index'),

			'visible'=>$this->auth->checkAccess('home',Yii::app()->user->id),

		),

		array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about'),

			'visible'=>$this->auth->checkAccess('about',Yii::app()->user->id),

		),

		array('label'=>'Contact', 'url'=>array('/site/contact'),

			'visible'=>$this->auth->checkAccess('contact',Yii::app()->user->id),

		),

		array('label'=>'Posts', 'url'=>array('/post/index'),

			'visible'=>$this->auth->checkAccess('posts',Yii::app()->user->id),

		),

		array('label'=>'PostsAdmin', 'url'=>array('/post/admin'),

			'visible'=>$this->auth->checkAccess('postsAdmin',Yii::app()->user->id),

		),

		array('label'=>'Login', 'url'=>array('/site/login'),

				

			'visible'=>$this->auth->checkAccess('login',Yii::app()->user->id),

		 ),

		array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'),

				

			'visible'=>$this->auth->checkAccess('logout',Yii::app()->user->id),

		 ),

	),

)); 



The above example does not make any sense, since we are dealing with simple one.

I hope it will be usefull when we have numerous menu items and complex user types or roles.

Regards.

I made a simple widget that can clean up the code. With the widget, you’d write:




$this->widget('zii.widgets.CMenu',array('items'=>array(	

	array('label'=>'Home', 'url'=>array('/site/index'),'authItem'=>'home'),

	array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about'),'authItem'=>'about'),

	...

))); 



Also, for future reference you can just call CWebUser->checkAccess, Yii::app()->user->checkAccess($item), and not have to pass the current user’s ID every time. Much easier to read :)