This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
lnauth/classes/lnAuth/Auth/ORM.php
2016-09-01 20:55:15 +10:00

220 lines
6.4 KiB
PHP

<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* Auth driver.
*
* @package lnAuth
* @category Classes
* @author Deon George
* @copyright (c) 2014 Deon George
* @license http://dev.leenooks.net/license.html
*/
abstract class lnAuth_Auth_ORM extends lnApp_Auth_ORM {
/**
* 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.
*/
protected function _get_token_user($token) {
// This has been implemented, as we sometimes we seem to come here twice
static $uo = NULL;
if (! is_null($uo))
return $uo;
$mmto = ORM::factory('Module_Method_Token',array('token'=>$token));
// Ignore the token if it doesnt exist.
if ($mmto->loaded()) {
// Check that the token is for this URI
$mo = ORM::factory('Module',array('name'=>Request::current()->controller()));
$mmo = $mo->module_method
->where('name','=',strtolower(Request::current()->directory() ? sprintf('%s:%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action()))
->find();
// Ignore the token if this is not the right method.
if ($mmo->id == $mmto->method_id) {
if (! is_null($mmto->date_expire) AND $mmto->date_expire < time()) {
SystemMessage::factory()
->title(_('Token Not Valid'))
->type('warning')
->body(_('Token expired'));
Session::instance()->delete('token');
$mmto->delete();
} elseif (! is_null($mmto->uses) AND $mmto->uses < 1) {
SystemMessage::factory()
->title(_('Token Not Valid'))
->type('warning')
->body(_('Token expired'));
Session::instance()->delete('token');
$mmto->delete();
} else {
// If this is a usage count token, reduce the count.
if (! is_null($mmto->uses))
$mmto->uses -= 1;
// Record the date this token was used
$mmto->date_last = time();
$mmto->save();
Session::instance()->set('token',$token);
$uo = ORM::factory('Account',$mmto->account_id);
$uo->log(sprintf('Token %s used for method %s [%s]',$mmto->token,$mmto->module_method->id,Request::current()->param('id')));
}
}
}
return $uo;
}
/**
* Logs a user in.
*
* @param string username
* @param string password
* @param boolean enable autologin
* @return boolean
*/
protected function _login($user,$password,$remember) {
if (! is_object($user)) {
$username = $user;
// Load the user
$user = ORM::factory('Account');
$user->where('username','=',$username)->find();
// If no user loaded, return
if (! $user->loaded())
return FALSE;
}
// Convert user password to new hash method
if (is_string($password) AND ! password_verify($password,$user->password) AND ! in_array($this->_config['hash_method'],['md5','sha1'])) {
// Was MD5
if (
(md5($password) == $user->password) OR
(sha1($password) == $user->password)
) {
// It will be re-hased by ORM
$user->password = $password;
if (! $user->save())
throw HTTP_Exception::factory(501,'Error converting password for :user',array(':user'=>$user->name()));
else {
SystemMessage::factory()
->title('Password Update')
->type('info')
->body('Your password was updated to a more secure algorithm');
}
}
}
// If the passwords match, perform a login
if ($user->active AND $user->has_any('group',ORM::factory('Group',array('name'=>'Registered Users'))->list_childgrps(TRUE)) AND password_verify($password,$user->password)) {
// @todo This is not currently used.
if ($remember === TRUE) {
// Create a new autologin token
$token = ORM::factory('User_Token');
// Set token data
$token->user_id = $user->id;
$token->expires = time() + $this->_config['lifetime'];
$token->save();
// Set the autologin cookie
Cookie::set('authautologin', $token->token, $this->_config['lifetime']);
}
// Record our session ID, we may need to update our DB when we get a new ID
$oldsess = session_id();
// Finish the login
$this->complete_login($user);
// Do we need to update databases with our new sesion ID
$sct = Kohana::$config->load('config')->session_change_trigger;
if (session_id() != $oldsess AND count($sct))
foreach ($sct as $t => $c)
if (Config::module_exist($t))
foreach (ORM::factory(ucwords($t))->where($c,'=',$oldsess)->find_all() as $o)
$o->set('session_id',session_id())
->update();
return TRUE;
}
// Login failed
return FALSE;
}
/**
* 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 ($token=Arr::get($_REQUEST,'token')))
$uo = $this->_get_token_user($token);
return $uo;
}
/**
* Authentication is controlled via database queries.
*
* This method can be used to test two situations:
* 1) Is the user logged in? ($role == FALSE)
* 2) Can the user run the current controller->action ($role == TRUE)
*
* @param boolean If authentication should be done for this module:method (ie: controller:action).
* @return boolean
*/
public function logged_in($role=NULL,$debug=NULL) {
$status = FALSE;
// If we are a CLI, we are not logged in
if (PHP_SAPI === 'cli')
return $status;
// Get the user from the session
$uo = $this->get_user();
// 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;
return $status;
}
}
?>