Friday, August 5, 2011

Module based login in YII Framework

Module based login

What is module?

From YII Framework documentation

 "A module is a self-contained software unit that consists of models, views, controllers and other supporting components. In many aspects, a module resembles to an application. The main difference is that a module cannot be deployed alone and it must reside inside of an application. Users can access the controllers in a module like they do with normal application controllers.

Modules are useful in several scenarios. For a large-scale application, we may divide it into several modules, each being developed and maintained separately. Some commonly used features, such as user management, comment management, may be developed in terms of modules so that they can be reused easily in future projects."

For example
admin users   = > index.php?r=admin/default/login
general users => index.php?r=user/default/login

To add module based login to a site without using RBAC, please follow these guidelines.
Consider the situation where we want to add 3 types of login in a site: customer, dealer, and admin.

Start by generating three modules using GII. (To do this, please refer to this guide for module generation http://yiiframework.com/doc/guide/1.1/en/basics.module#creating-module)

Step 1
Copy the UserIdentity component to the module/components folder for each module. We will validate each module against its table. For example, customer validation is done using customer table, and admin validation against the admin table

For each module, change its UserIdentity authenticate() function to perform the appropriate validation.


Step 2
For each module, add the following lines to its main page. For example, for the Customer module, add to Customer/CustomerModule.php Add the following lines to init():

$this->setComponents(array(
'errorHandler' => array(
'errorAction' => 'customer/default/error'),
'user' => array(
'class' => 'CWebUser',             
'loginUrl' => Yii::app()->createUrl('customer/default/login'),
)
));

Yii::app()->user->setStateKeyPrefix('_customer');

Step 3
Create the login/logout action in each module's DefaultController.
For example, for the Customer module:
Create the actionLogin() in Customer/controllers/DefaultController.php.
Also, create actionLogout() as follows:

public function actionLogout() {
Yii::app()->user->logout(false);
$this->redirect(Yii::app()->getModule('customer')->user->loginUrl);
}

Point sub-domain to module
This tips from the forum URL Subdomain to module
There is a feature called "Parameterizing Hostnames" (described on this pages). add the following lines to main.php

'components' => array(
...
'urlManager' => array(
'rules' => array(
'http://customer.example.com' => 'customer/default/index',
'http://customer.example.com/login' => 'customer/default/login',
),
),
...
),
So "customer/default/index" refers to the module "customer" with controller "default" and action "index".


Update
Redirect to respective module login, if user not logged in to a particular model
add following code to customer module CustomerModule.php in beforeControllerAction

if(Yii::app()->getModule('customer')->user->isGuest)
Yii::app()->getModule('customer')->user->setReturnUrl('customer/default/login');
do the same for other module
in SiteController's site/login method
public function actionLogin() {
Yii::app()->request->redirect(Yii::app()->createUrl(Yii::app()->user->returnUrl));
}
(or)

Another method(Recommended)
Redirect to respective module login, if user not logged in to a particular model
add following code to customer module CustomerModule.php
public function beforeControllerAction($controller, $action) {
if (parent::beforeControllerAction($controller, $action)) {
// this method is called before any module controller action is performed
// you may place customized code here
$route = $controller->id . '/' . $action->id;
// echo $route;
$publicPages = array(
'default/login',
'default/error',
);
if (Yii::app()->user->isGuest && !in_array($route, $publicPages)){            
Yii::app()->getModule('customer')->user->loginRequired();                
}
else
return true;
}
else
return false;
}

do the same for other module
Thanks to ricardograna for sharing some configurations

1 comment:

Radley Co Tad said...
This comment has been removed by a blog administrator.