Save user's last log out - yii

I am trying to save user's last logout time into a DB in Yii framework.
I have WebUser as:
<?php
// this file must be stored in:
// protected/components/WebUser.php
class WebUser extends CWebUser {
public function afterLogout()
{
$user=user::Model();
$user->logOutDateTime='TEST';
$user->saveAttributes(array('logOutDateTime'));
parent::afterLogout();
}
}
?>
and in config\main.php I have these lines
// application components
'components'=>array(
'user'=>array(
// enable cookie-based authentication
'class'=>'WebUser',
'allowAutoLogin'=>true,
)
For now I have set logOutDateTime datatype to varchar, to test, and I assume every time user logs out, it should write 'TEST' into database but it does nothing.
Where did I go wrong?

I don't think the afterLogout() still has the Yii::app()->user set, so I would do something like (untested):
public function beforeLogout()
{
if (parent::beforeLogout()) {
$user = User::model()->findByPk(Yii::app()->user->id); // assuming you have getId() mapped to id column
$user->logOutDateTime='TEST';
$user->saveAttributes(array('logOutDateTime'));
return true;
} else {
return false;
}
}

$user = user::Model();
should be:
$user = user::Model()->find(/* model_conditions */);

Related

yii generatepasswordhash not working

For some strange reasons, i am finding it difficult to login with yii->$app->generatePasswordhash($password.) I have a backedn where i register users and also change password. Users can login successfully when i created them but when i edit user password, the system keeps telling me invalid username or password. Below is my code.
//Model
Class Adminuser extends ActiveRecord
{
public $resetpassword
public function activateuser($id,$newpassword)
{
//echo Yii::$app->security->generatePasswordHash($newpassword); exit;
$user = Adminuser::find()->where(['id' =>$id])->one();
$user->status = self::SET_STATUS;
$user->password_reset_token = null;
$user->password = Admin::genPassword($this->resetpassword); // this returns yii::$app->security->generatePasswordHash($password)
return $user->save();
}
}
//controller action
public function actionActivate($id)
{
$model = new Adminuser();
$model->scenario = 'adminactivate';
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if($model->activateuser($id,$model->password))
{
//send a mail
Yii::$app->session->setFlash('success', 'New user has been activated.');
return $this->redirect(['index']);
}
else
$errors = $model->errors;
}
return $this->render('activate', [
'model' => $model,
]);
}
Please i need help
Your activateuser() method has $newpassword as an incoming parameter. Anyway you are using $this->resetpassword in Admin::genPassword(). Looks like that is the reason of the problem and all your passwords are generated based on null value. So try to use $user->password = Admin::genPassword($newpassword); instead.

how to get or create role in yii

I am a newbie to yii. I have stuck my mind with yii-tutorials for creating roles in yii. but I am not getting how can I create role in yii. means I want to create two roles admin & staff and I want to give different priviliage to them.
I have created a role in user table, but I am not getting that how can I create a role and can assign priviliages to them, please help me guys
Thanks in advance
In your copenents/UserIdentity.php
class UserIdentity extends CUserIdentity{
private $_id;
public function authenticate()
{
$record=Members::model()->findByAttributes(array('username'=>trim($this->username)));
if($record===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($record->password!==md5(trim($this->password)))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$record->id;
$this->setState('username', $record->username);
$this->setState('name', $record->name);
$this->setState('type', $record->role);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId()
{
return $this->_id;
}
public function setId($id)
{
$this->_id = $id;
}
}
You can create a new column name as "role". set the members type "admin" or "staff" to role column.
Be careful to that line.
$this->setState('type', $record->role);
Create a new helper file. /protected/helpers/RoleHelper.php
class RoleHelper {
public static function GetRole(){
if (Yii::app()->user->type == "admin"){
//set the actions which admin can access
$actionlist = "'index','view','create','update','admin','delete'";
}
elseif (Yii::app()->user->type = "staff"){
//set the actions which staff can access
$actionlist = "'index','view','create','update'";
}
else {
$actionlist = "'index','view'";
}
return $actionlist;
}
}
and in your controllers -> accessRules function
public function accessRules()
{
return array(
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array(RoleHelper::GetRole()),
'users'=>array('#'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
and dont forget to add 'application.helpers.*' to /config/main.php
'import'=>array(
'application.models.*',
'application.components.*',
'application.helpers.*',
),
This source is pretty good specially for beginners..I am using this method till now:
Simple RBAC in YII
Just follow the instructions given while having your desired modifications.
Concrete Example:
WebUser.php (/components/WebUser.php)
<?php
class WebUser extends CWebUser
{
/**
* Overrides a Yii method that is used for roles in controllers (accessRules).
*
* #param string $operation Name of the operation required (here, a role).
* #param mixed $params (opt) Parameters for this operation, usually the object to access.
* #return bool Permission granted?
*/
public function checkAccess($operation, $params=array())
{
if (empty($this->id)) {
// Not identified => no rights
return false;
}
$role = $this->getState("evalRoles");
if ($role === 'SuperAdmin') {
return 'SuperAdmin'; // admin role has access to everything
}
if ($role === 'Administrator') {
return 'Administrator'; // admin role has access to everything
}
if ($role === 'Professor') {
return 'Professor'; //Regular Teaching Professor, has limited access
}
// allow access if the operation request is the current user's role
return ($operation === $role);
}
}
Just connect it with your components/UserIdentity.php and config/main.php:
'components' => array(
// ...
'user' => array(
'class' => 'WebUser',
),
and thats it..
to check the role of the logged in:
Yii::app->checkAccess("roles");
where checkAccess is the name of your function in WebUser...
Please note that evalRoles is a column in your table that will supply the role of an account (on my link provided, that would be the word roles used in the major part snippet)

UserIdentity and session issue

I have the following class. But when I try to access the Yii::app()->user->realName; it generates an error.
I can't understand it all. please help!
Following code is the code of my UserIdentity class.
<?php
/**
* UserIdentity represents the data needed to identity a user.
* It contains the authentication method that checks if the provided
* data can identity the user.
*/
class UserIdentity extends CUserIdentity {
public $id, $dmail, $real_name;
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* #return boolean whether authentication succeeds.
*/
public function authenticate() {
$theUser = User::model()->findByAttributes(array(
'email' => $this->username,
// 'password' => $this->password
));
if ($theUser == null) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} else {
$this->id = $theUser->id;
$this->setState('uid', $this->id);
// echo $users->name; exit;
// $this->setState('userName', $theUser->name);
$this->setState("realName",$theUser->fname .' '. $theUser->lname);
$this->errorCode = self::ERROR_NONE;
}
return!$this->errorCode;
}
}
?>
You need to extend the CWebUser class to achieve the results you want.
class WebUser extends CWebUser{
protected $_realName = 'wu_default';
public function getRealName(){
$realName = Yii::app()->user->getState('realName');
return (null!==$realName)?$realName:$this->_realName;
}
public function setRealName($value){
Yii::app()->user->setState('realName', $value);
}
}
You can then assign and recall the realName attribute by using Yii::app()->user->realName.
The protected $_realName is optional, but allows you to define a default value. If you choose not to use it, change the return line of the getRealName method to return $realName.
Place the above class in components/WebUser.php, or anywhere that it will be loaded or autoloaded.
Change your config file to use your new WebUser class and you should be all set.
'components'=>
'user'=>array(
'class'=>'WebUser',
),
...
),

How do you add more error codes for user login on YII?

In yii I can use:
self::ERROR_USERNAME_INVALID;
I want another one:
self::ERROR_USER_BANNED;
That must give the error:
Sorry, but you cannot login because you account has been blocked.
How do I set this up?
Add it directly to your protected/components/UserIdentity.php :
class UserIdentity extends CUserIdentity {
const ERROR_USER_BANNED = -1; // say -1 you have to give some int value
public function authenticate() {
// ... code ...
if (/* condition to check for banning */) { // you might want to put this check right after any other username checks, and before password checks
$this->errorCode=self::ERROR_USER_BANNED;
$this->errorMessage='Sorry, but you cannot login because your account has been blocked.'
return $this->errorCode;
}
}
}
The default way with LoginForm.php model :
Add a new validator rule, say to your username field:
public function rules() {
return array(
// ... other rules ...
array('username','isBanned')
);
}
// the isbanned validator
public function isBanned($attribute,$params) {
if($this->_identity===null)
$this->_identity=new UserIdentity($this->username,$this->password);
if($this->_identity->authenticate() === UserIdentity::ERROR_USER_BANNED){
$this->addError($attribute,$this->_identity->errorMessage);
}
Ofcourse you could have declared another function in UserIdentity to check just for banning, and call that function from the isBanned validator, instead of having things in the authenticate function.
add following in UserIdentity.php
const ERROR_USER_BANNED = 12 ; #or whateve int value you prefer
public function getErrorMessageX() #or whatever method name
{
switch ($this->errorCode)
{
case self::ERROR_USER_BANNED:
return 'sorry, your account has been banned'; # custom error msg
case self::ERROR_USERNAME_INVALID:
return 'User does not exists';
case self::ERROR_PASSWORD_INVALID:
return 'Password does not match';
case self::ERROR_ACCOUNT_NOT_CONFIRMED: #this one is mine:)
return 'This Account needs confirmation';
}
}
now in LoginForm.php
public function authenticate( )
{
$this->_identity = new UserIdentity($this->username,$this->password);
if( $this->_identity->authenticate() === FALSE )
$this->addError('username', $this->_identity->errorMessageX); #here
#some more code
return !$this->_identity->errorCode;
}

How to set default action dynamically in Yii

i want to change default action of a controller depends on which user is logged in.
Ex. There are two users in my site : publisher and author and i want to set publisher action as default action when a publisher is logged in, and same for author.
what should i do? when can I check my roles and set their relevant actions?
Another way to do this would be setting the defaultAction property in your controller's init() method. Somewhat like this:
<?php
class MyAwesomeController extends Controller{ // or extends CController depending on your code
public function init(){
parent::init(); // no need for this call if you don't have anything in your parent init()
if(array_key_exists('RolePublisher', Yii::app()->authManager->getRoles(Yii::app()->user->id)))
$this->defaultAction='publisher'; // name of your action
else if (array_key_exists('RoleAuthor', Yii::app()->authManager->getRoles(Yii::app()->user->id)))
$this->defaultAction='author'; // name of your action
}
// ... rest of your code
}
?>
Check out CAuthManager's getRoles(), to see that the returned array will have format of 'role'=>CAuthItem object, which is why i'm checking with array_key_exists().
Incase you don't know, the action name will be only the name without the action part, for example if you have public function actionPublisher(){...} then action name should be: publisher.
Another, simpler, thing you can do is keep the default action the same, but that default action simply calls an additional action function depending on what kind of user is logged in. So for example you have the indexAction function conditionally calling this->userAction or this->publisherAction depending on the check for who is logged in.
I think you can save "first user page" in user table. And when a user is authenticated, you can load this page from database. Where you can do this? I think best place is UserIdentity class. After that, you could get this value in SiteController::actionLogin();
You can get or set "first page" value:
if (null === $user->first_page) {
$firstPage = 'site/index';
} else {
$firstPage = $user->first_page;
}
This is a complete class:
class UserIdentity extends CUserIdentity
{
private $_id;
public function authenticate()
{
$user = User::model()->findByAttributes(array('username' => $this->username));
if ($user === null) {
$this->errorCode = self::ERROR_USERNAME_INVALID;
} else if ($user->password !== $user->encrypt($this->password)) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} else {
$this->_id = $user->id;
if (null === $user->first_page) {
$firstPage = 'site/index';
} else {
$firstPage = $user->first_page;
}
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId()
{
return $this->_id;
}
}
/**
* Displays the login page
*/
public function actionLogin()
{
$model = new LoginForm;
// if it is ajax validation request
if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if (isset($_POST['LoginForm'])) {
$model->attributes = $_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if ($model->validate() && $model->login())
$this->redirect(Yii::app()->user->first_page);
}
// display the login form
$this->render('login', array('model' => $model));
}
Also, you can just write right code only in this file. In SiteController file.