Login/Activation tested

This commit is contained in:
Deon George
2014-10-02 15:33:07 +10:00
parent 037633f084
commit a7ed6672e1
18 changed files with 340 additions and 51 deletions

View File

@@ -23,6 +23,22 @@ abstract class lnApp_Auth_ORM extends Kohana_Auth_ORM {
parent::__construct($config);
}
/**
* Get the user that a token applies to
*
* This will check that the token is valid (not expired and for the request)
*
* @param $token The token
* @return Model_Account|NULL The user that the token is valid for.
*/
private function _get_token_user($token) {
list($id,$key) = explode(':',$token,2);
$uo = ORM::factory('Account',$id);
return ($uo->token(NULL,NULL,NULL,NULL) == $token) ? $uo : NULL;
}
/**
* Logs a user in.
*
@@ -50,6 +66,9 @@ abstract class lnApp_Auth_ORM extends Kohana_Auth_ORM {
// If we have the right password, we'll check the status of the account
if ($user->password === $password AND $user->active) {
if (! $user->activated())
HTTP::redirect(URL::link('user','account/activate'));
// Record our session ID, we may need to update our DB when we get a new ID
$oldsess = session_id();
@@ -65,10 +84,6 @@ abstract class lnApp_Auth_ORM extends Kohana_Auth_ORM {
$o->set('session_id',session_id())
->update();
//@TODO
if (! $user->has_any('group',ORM::factory('Group',array('name'=>'Registered Users'))->list_childgrps(TRUE)))
HTTP::redirect(URL::link('user','account/activate'));
return TRUE;
}
@@ -90,6 +105,28 @@ abstract class lnApp_Auth_ORM extends Kohana_Auth_ORM {
return is_null($x=$this->get_user()) ? ORM::factory('Group')->where('id','=',0)->find_all() : $x->groups();
}
/**
* Gets the currently logged in user from the session.
* Returns NULL if no user is currently logged in.
*
* @param boolean Check token users too
* @return mixed
*/
public function get_user($default=NULL,$tokenuser=TRUE) {
// If we are a CLI, we are not logged in
if (PHP_SAPI === 'cli')
throw new Kohana_Exception('Calling :method from the CLI is not allowed!',array(':method'=>__METHOD__));
// Get the current user
$uo = parent::get_user($default);
// If we are not logged in, see if there is token for the user
if (is_null($uo) AND $tokenuser AND ($token=Session::instance()->get('token')) OR (! empty($_REQUEST['token']) AND $token=$_REQUEST['token']))
$uo = $this->_get_token_user($token);
return $uo;
}
// Override Kohana Auth requirement to have a hash_key
public function hash($str) {
switch ($this->_config['hash_method']) {
@@ -100,7 +137,7 @@ abstract class lnApp_Auth_ORM extends Kohana_Auth_ORM {
}
/**
* OSB authentication is controlled via database queries.
* lnApp authentication is controlled via database queries.
*
* This method can be used to test two situations:
* 1) Is the user logged in? ($role == FALSE)
@@ -121,18 +158,7 @@ abstract class lnApp_Auth_ORM extends Kohana_Auth_ORM {
// If we are not a valid user object, then we are not logged in
if (is_object($uo) AND ($uo instanceof Model_Account) AND $uo->loaded())
if (! empty($role)) {
if (($x = Request::current()->mmo()) instanceof Model)
// If the role has the authorisation to run the method
foreach ($x->group->find_all() as $go)
if ($go->id == 0 OR $uo->has_any('group',$go->list_childgrps(TRUE))) {
$status = TRUE;
break;
}
// There is no role, so the method should be allowed to run as anonymous
} else
$status = TRUE;
$status = TRUE;
return $status;
}

View File

@@ -0,0 +1,14 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides account management
*
* @package lnApp
* @category Controllers
* @author Deon George
* @copyright (c) 2014 Deon George
* @license http://dev.leenooks.net/license.html
*/
abstract class lnApp_Controller_Account extends Controller_TemplateDefault {
}
?>

View File

@@ -25,21 +25,15 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
HTTP::redirect('login');
elseif ($ao->activate_code() == $this->request->post('code')) {
$go = ORM::factory('Group',array('name'=>'Registered Users'));
$ago = ORM::factory('Account_Group',array('account_id'=>$ao,'group_id'=>$go));
if (! $ago->loaded()) {
$ago->account_id=$ao;
$ago->group_id=$go;
}
$ago->active = TRUE;
$ago->save();
$ao->verified = TRUE;
$ao->save();
SystemMessage::factory()
->title(_('Account Activated'))
->type('info')
->body(_('Your account has been activated.'));
HTTP::redirect('welcome');
}
}
@@ -82,6 +76,7 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
// Log the password reset
$ao->log('Activation code sent');
Session::instance()->set('activate',$ao);
}
}
@@ -167,10 +162,33 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
$ao = ORM::factory('Account',$this->request->param('id'));
if ($this->request->post() AND $ao->values($this->request->post())->changed() AND (! $this->save($ao)))
$ao->reload()->values($this->request->post());
$ao->reload()->values($this->request->post());
if ($ao->loaded())
HTTP::redirect('login');
if ($ao->loaded()) {
$co = Company::instance();
// Send our email with the token
$email = Email::factory('login_activate')
->set('SITE',URL::base(TRUE,TRUE))
->set('SITE_ADMIN',$co->admin()->name())
->set('CODE',$ao->activate_code())
->set('EMAIL',$ao->email)
->set('ID',$ao->id)
->set('USER_NAME',$ao->name());
$email->to = array('email'=>array($ao->email=>$ao->name()));
$email->from = array('email'=>array($co->admin()->email=>$co->admin()->name()));
$email->subject = 'Please activate your account for '.$co->name();
$email->deliver();
SystemMessage::factory()
->title(_('Account Registered'))
->type('info')
->body(_('Please check your email for more instructions!'));
Session::instance()->set('activate',$ao);
HTTP::redirect('login/activate/'.$ao->id);
}
Block::factory()
->type('form-horizontal')
@@ -184,33 +202,26 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
*/
public function action_reset() {
// Minutes to keep our token
$token_expire = 15;
$co = Company::instance();
// If user already signed-in
if (Auth::instance()->logged_in())
HTTP::redirect('welcome/index');
$token_expire = 15*60;
// If the user posted their details to reset their password
if ($this->request->post()) {
// If the username is correct, create a method token
if ($ao=ORM::factory('Account',array('email'=>$this->request->post('username'))) AND $ao->loaded()) {
$mmto = ORM::factory('Module_Method_Token')
->method(array('account','user:resetpassword'))
->account($ao)
->uses(2)
->expire(time()+$token_expire*60);
$token = $ao->token($token_expire,'account','user:resetpassword',2);
if ($token) {
$co = Company::instance();
if ($mmto->generate()) {
// Send our email with the token
$email = Email::factory('login_reset')
->set('SITE',URL::base(TRUE,TRUE))
->set('SITE_ADMIN',$co->admin()->name())
->set('TOKEN',$mmto->token)
->set('TOKEN',$token)
->set('TOKEN_EXPIRE_MIN',$token_expire)
->set('USER_NAME',$mmto->account->name());
->set('USER_NAME',$ao->name());
$email->to = array('email'=>array($mmto->account->email=>$mmto->account->name()));
$email->to = array('email'=>array($ao->email=>$ao->name()));
$email->from = array('email'=>array($co->admin()->email=>$co->admin()->name()));
$email->subject = 'Login Reset Token for '.$co->name();
$email->deliver();

View File

@@ -68,6 +68,8 @@ abstract class lnApp_Controller_TemplateDefault extends Kohana_Controller_Templa
* @uses meta
*/
public function before() {
$this->ao = Auth::instance()->get_user();
// Actions that start with ajax, should only be ajax
if (! Kohana::$config->load('debug')->ajax AND preg_match('/^ajax/',Request::current()->action()) AND ! Request::current()->is_ajax())
throw HTTP_Exception::factory(412,_('Unable to fulfil request.'));

View File

@@ -0,0 +1,72 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides User Account Update functions
*
* @package lnApp
* @category Controllers/User
* @author Deon George
* @copyright (c) 2009-2013 Deon George
* @license http://dev.leenooks.net/license.html
*/
abstract class lnApp_Controller_User_Account extends Controller_Account {
protected $secure_actions = array(
'edit'=>TRUE,
'resetpassword'=>TRUE,
);
/**
* Enable User to Edit their Account Details
*/
public function action_edit() {
if ($_POST AND $this->ao->values($_POST)->changed() AND (! $this->save($this->ao)))
$this->ao->reload();
Block::factory()
->title(sprintf('Account: %s',$this->ao->accnum()))
->title_icon('fa-wrench')
->type('form-horizontal')
->body(View::factory('account/user/edit')->set('o',$this->ao));
}
public function action_resetpassword() {
if ($this->request->post()) {
$validation = Validation::factory($this->request->post())
->rule('password','not_empty')
->rule('password','min_length',array(':value',6))
->rule('password_confirm','matches',array(':validation',':field','password'));
// Store our new values
$this->ao->values($this->request->post());
if (! $validation->check())
SystemMessage::factory()
->title(_('Record NOT updated'))
->type('error')
->body(_('Your password didnt pass validation.'));
// Run validation and save
elseif ($this->ao->changed())
if ($this->ao->save()) {
SystemMessage::factory()
->title('Record updated')
->type('success')
->body(_('Your account record has been updated.'));
// Log the password reset
$this->ao->log('Password reset');
}
HTTP::redirect('login');
}
Block::factory()
->title(sprintf('Password Reset: %s',$this->ao->accnum()))
->title_icon('fa-cog')
->id('reset')
->type('form-horizontal')
->body(View::factory('account/user/resetpassword')->set('o',$this->ao));
}
}
?>

View File

@@ -50,7 +50,7 @@ abstract class lnApp_Model_Account extends Model_Auth_UserDefault {
}
public function activated() {
return $this->has_any('group',ORM::factory('Group',array('name'=>'Registered Users'))->list_childgrps(TRUE));
return $this->verified;
}
/**
@@ -68,6 +68,9 @@ abstract class lnApp_Model_Account extends Model_Auth_UserDefault {
}
public function log($message) {
if (! class_exists('Model_Account_Log'))
return TRUE;
// Log a message for this account
$alo = ORM::factory('Account_Log');
$alo->account_id = $this->id;
@@ -110,6 +113,13 @@ abstract class lnApp_Model_Account extends Model_Auth_UserDefault {
return trim(sprintf('%s %s',$this->first_name,$this->last_name));
}
/**
* Return a token valid for this user
*/
public function token($token_expire,$module,$method,$uses) {
return $this->id.':'.md5(sprintf('%s-%s',$this->accnum(),$this->date_last));
}
/**
* Search for accounts matching a term
*/

View File

@@ -14,6 +14,7 @@ abstract class lnApp_Model_Auth_UserDefault extends Model_Auth_User {
public function rules() {
return array(
'email' => array(
array(array($this, 'unique'), array('email', ':value')),
array('not_empty'),
array('min_length', array(':value', 4)),
array('max_length', array(':value', 127)),