Revision #8 was created by waterloomatt on Nov 1, 2011, 2:12:41 AM.
Added WebUser class, added Time helper class, refactored ChangePasswordRule->changePasswordRequired to use the Time helper class
Content
[...]
{
public $passwordExpiry;
/**
* Checks if a user is required to change their password.
* @param type $user the user whose password needs to be validated
* @return boolean if the user must change their password
*/
public function changePasswordRequired($user)
{
$passwordChangeRequired = false;
if ($user->daysSincePasswordChange() > $this->passwordExpiry)
$passwordChangeRequired = true;
return $passwordChangeRequired;
}
}
?>
```
Controller Class (Parent Controller - client controllers should extend this one). These two methods instantiate the filter and link it to all controllers that inherit from this one.
```php
/**
* Creates a rule to validate user's password freshness.
* @return array the array of rules to validate against
*/
public function changePasswordRules()
{
return array(
'days' => 30,
);
}
/**
* Runs the Password filter
* @param type $filterChain
*/
public function filterChangePassword($filterChain)
{
$filter = new ChangePasswordFilter();
$filter->setRules($this->changePasswordRules());
$filter->filter($filterChain);
}
```
Client Controller Class. This is an example of my SiteController. The changePasswordFilter applies to all actions except for the ones listed after "-".
```php
/**
* @return array action filters
*/
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
* Returns the number of days between two time intervals. If $end is null, 'now' will be used.
* @param string $start the start time. Should be an English textual description. Ex: 2011-06-28 08:06:53
* @param string $end the end time. Should be an English textual description. Ex: 2011-06-28 08:06:53
* @return integer the number of days
*/
public function calculateInterval($start, $end = null)
{
$startTime = strtotime($start);
$endTime = ($end == null) ? time() : $end;
$elapsedTime = abs($endTime - $startTime);
return round($elapsedTime / 86400);
}
```
The redirectToPasswordForm method. I include this in WebUser. It is copied from CWebUser->loginRequired() but redirects to the password form, instead of the login form.
Controller Class (Parent Controller - client controllers should extend this one). These two methods instantiate the filter and link it to all controllers that inherit from this one.
```php
/**
* Creates a rule to validate user's password freshness.
* @return array the array of rules to validate against
*/
public function changePasswordRules()
{
return array(
'days' => 30,
);
}
/**
* Runs the Password filter
* @param type $filterChain
*/
public function filterChangePassword($filterChain)
{
$filter = new ChangePasswordFilter();
$filter->setRules($this->changePasswordRules());
$filter->filter($filterChain);
}
```
Client Controller Class. This is an example of my SiteController. The changePasswordFilter applies to all actions except for the ones listed after "-".
```php
/**
* @return array action filters
*/
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
The redirectToPasswordForm method. I include this in WebUser. It is copied from CWebUser->loginRequired() but redirects to the password form, instead of the login form.
```php
<?php
/**
* WebUser class file.
*
* @author Matt Skelton
* @date 8-Jun-2011
*/
/**
* Provides additional properties and functionality to CWebUser.
*/
class WebUser extends CWebUser
{
// User access error codes
const ERROR_NONE = 1;
const ERROR_NEW_USER = 2;
const ERROR_PASSWORD_EXPIRED = 3;
private $accessError = self::ERROR_NONE;
/**
* Holds a reference to the currently logged in user model.
* @var User The currently logged in User Model.
*/
private $_model;
public $changePasswordUrl = array('/user/password');
public function init()
{
parent::init();
}
/**
* Returns the User model of the currently logged in user and null if
* is user is not logged in.
*
* @return User The model of the logged in user.
*/
public function getModel()
{
return $this->loadUser(Yii::app()->user->id);
}
/**
* Returns a boolean indicating if the currently logged in user is an Admin user.
* @return boolean whether the current application user is an admin.
*/
public function getIsAdmin()
{
$isAdmin = false;
if (strtolower($this->loadUser(Yii::app()->user->id)->role->name) == 'admin' ||
* Returns a UNIX timestamp, given either a UNIX timestamp or a valid strtotime() date string.
*
* @param string $dateString Datetime string
* @param int $userOffset User's offset from GMT (in hours)
* @return string Parsed timestamp
*/
public static function fromString($dateString, $userOffset = null)
{
if (empty($dateString))
{
return false;
}
if (is_integer($dateString) || is_numeric($dateString))
{
$date = intval($dateString);
}
else
{
$date = strtotime($dateString);
}
if ($userOffset !== null)
{
return $this->convert($date, $userOffset);
}
if ($date === -1)
{
return false;
}
return $date;
}
}
?>
```
The rule setup in Controller.php, _'days' => 30,_, is obviously very simple. It can be easily extended. For example, users of different roles might have different freshness requirements - Admin users - 10 days, regular users - 30 days, super admins - never etc. You'll just need to modify _ChangePasswordFilter->setRules()_ and _ChangePasswordRule->changePasswordRequired()_ to loop over the list of rules and perform your needed logic.