Difference between #2 and #3 of Simple access control

unchanged
Title
Simple access control
unchanged
Category
Tutorials
unchanged
Tags
simple, access, control, accessControl, accessRules, allow, deny, user, users
changed
Content
For those who feel, the Controller->accessRules() or RBAC (Role-Based Access
Control) is too complicated or doesn't want the
username(s)lengthily to be hard-coded in
accessRules(),code, here is a very simple, easy-to-implement
solution.

Considerations
--------------
As usual, you will have a table, holding the user's data, such as: username,
password, email, real_name, etc. To store the user rights, you need an
additional field, named **admin_level**. This will be an unsigned tinyint, and
will hold the user's rights to do things around the site.
You will define the admin levels, according to your needs. Now, for this
example, let's define 4 levels:
0: REGULAR_USER - basic access
1: EDITOR - access to product editing, translations, etc.
2: MANAGER - Higher level control: site settings, statistics, etc.
3: ADMIN - Delete/modify users, modify critical site settings, handle money,
etc.

Implementation
--------------
### Step 1. Create/modify the user table:
~~~
[sql]
CREATE TABLE `users` (
	`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
	`username` varchar(25) CHARACTER SET ascii NOT NULL,
	`password` varchar(128) COLLATE utf8_bin NOT NULL,
	`email` varchar(100) COLLATE utf8_bin NOT NULL,
	`admin_level` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0: regular
user; 1: editor; 2: manager; 3: admin'
)
~~~
### Step 2. Create the user login-logout mechanism
Following the standard, recommended procedure, you will have a login-logout
functionality.
### Step 3. Define the user levels and create the access-control functionality.
Open the protected/components/Controller.php file and add the following to the
beginning of the file:
~~~
[php]
define('REGULAR_USER', 0);
define('EDITOR', 1);
define('MANAGER', 2);
define('ADMIN', 3);
~~~
You will load and store the user's data every time a page is requested. To do
this, modify the Controller class as follows:

Add a **userData** property:

~~~
[php]
public $userData; // Holds an activeRecord with current user. NULL if guest
~~~

Define (or extend) the **init()** function:

~~~
[php]
public function init() {
	...
	// Load the user
	if (!Yii::app()->user->isGuest)
		$this->userData =
AR_Users::model()->findByPk(Yii::app()->user->id);
	...
}
~~~

Add the **allowUser** function:

~~~
[php]
public function allowUser($min_level) { //-1 no login required 0..3: admin level
	$current_level = -1;
	if ($this->userData !== null)
		$current_level = $this->userData->admin_level;
	if ($min_level > $current_level) {
		throw new CHttpException(403, 'You have no permission to view this content');
	}
}
~~~

### Step 4. Begin your controller actions calling the **allowUser()** function.

If the current user will not have the required admin level, a CHttpException
will be thrown. If you don't need any access control, don't use the
**allowUser()** function.

~~~
[php]
class SomeController extends Controller {

	public function actionIndex() {
		// $this->allowUser(REGULAR_USER); // everybody can view index
		$this->render('index');
	}

	public function actionLogin() {
		// $this->allowUser(REGULAR_USER); // everybody can log in
		$this->render('login', array(...));
	}

	public function actionEditproduct($id) {
		$this->allowUser(EDITOR); // only editors, managers and admins can edit
products
		...
		$this->render('editproduct', array(...));
	}

	public function actionSitesettings($id) {
		$this->allowUser(MANAGER); // only managers and admins can change site
settings
		...
		$this->render('sitesettings', array(...));
	}

	public function actionEdituser($id) {
		$this->allowUser(ADMIN); // only admins can change user data
		...
		$this->render('edituser', array(...));
	}

}
~~~

Final words
--------------
- you can use the userData property to check, display or even modify user data.
If userData === null, there is no user logged in, so you need to check first
this.
- the userData->admin_level can be edited along with the other user data, so
everybody's rights can be changed (by an admin)
- the user rights will be hard-coded. This will help not tech-guru site owners
to manage their subscribed members, especially to allow/disallow employees to
do/see certain tasks on the site.