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.
khosb/application/classes/auth/osb.php
2012-01-12 19:53:56 +11:00

287 lines
8.8 KiB
PHP

<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* OSB Auth driver.
*
* @package OSB
* @subpackage Account
* @category Auth
* @author Deon George
* @copyright (c) 2010 Deon George
* @license http://dev.leenooks.net/license.html
*/
class Auth_OSB extends Auth_ORM {
/**
* OSB 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;
// Get the user from the session
$user = $this->get_user(FALSE);
// If we are not a valid user object, then we are not logged in
if (is_object($user) AND $user instanceof Model_Account AND $user->loaded()) {
if (Config::sitemode() == Kohana::DEVELOPMENT && Kohana::config('config.site_debug'))
SystemMessage::add(array('title'=>'Debug','type'=>'debug','body'=>Kohana::debug(array('user'=>$user->username,'r'=>$role))));
if (! empty($role)) {
// Get the module details
$mo = ORM::factory('module',array('name'=>Request::current()->controller()));
if (! $mo->loaded() OR ! $mo->status) {
SystemMessage::add(array(
'title'=>'Module is not defined or active in the Database',
'type'=>'warning',
'body'=>sprintf('Module not defined: %s',Request::current()->controller()),
));
} else {
if (Request::current()->directory())
$method_name = sprintf('%s_%s',Request::current()->directory(),Request::current()->action());
else
$method_name = Request::current()->action();
// Get the method number
$mmo = ORM::factory('module_method',array('module_id'=>$mo->id,'name'=>$method_name));
if (! $mmo->loaded()) {
SystemMessage::add(array(
'title'=>'Method is not defined or active in the Database',
'type'=>'warning',
'body'=>sprintf('Method not defined: %s for %s',Request::current()->action(),$mo->name),
));
} else {
// If the role has the authorisation to run the method
$gmo = ORM::factory('group_method')
->where('method_id','=',$mmo->id);
$roles = '';
foreach ($gmo->find_all() as $gm) {
$roles .= ($roles ? '|' : '').$gm->group->name;
// $gm->group->id == 0 means all users.
if ($gm->group->id == 0 OR $user->has_any('group',$gm->group->list_childgrps(TRUE))) {
$status = TRUE;
$roles = '';
break;
}
}
if (! $status) {
if (Config::sitemode() == Kohana::DEVELOPMENT)
SystemMessage::add(array(
'title'=>'User is not authorised in Database',
'type'=>'debug',
'body'=>sprintf('Role(s) checked: %s<br/>User: %s</br>Module: %s<br/>Method: %s',$roles,$user->username,$mo->name,$mmo->name),
));
}
}
}
if (Config::sitemode() == Kohana::DEVELOPMENT)
SystemMessage::add(array(
'title'=>'Debug',
'type'=>'debug',
'body'=>sprintf('A-User: <b>%s</b>, Module: <b>%s</b>, Method: <b>%s</b>, Role: <b>%s</b>, Status: <b>%s</b>, Data: <b>%s</b>',
$user->username,Request::current()->controller(),Request::current()->action(),$role,$status,$debug)));
// There is no role, so the method should be allowed to run as anonymous
} else {
if (Config::sitemode() == Kohana::DEVELOPMENT)
SystemMessage::add(array(
'title'=>'Debug',
'type'=>'debug',
'body'=>sprintf('B-User: <b>%s</b>, Module: <b>%s</b>, Method: <b>%s</b>, Status: <b>%s</b>, Data: <b>%s</b>',
$user->username,Request::current()->controller(),Request::current()->action(),'No Role Default Access',$debug)));
$status = TRUE;
}
// Check and see if we have a token to login and run the method
} elseif ((! empty($_REQUEST['token']) AND $token = $_REQUEST['token']) OR $token=Session::instance()->get('token')) {
if ($user=$this->_get_token_user($token) AND $user !== FALSE)
$status = TRUE;
} else {
if (Config::sitemode() == Kohana::DEVELOPMENT)
SystemMessage::add(array('title'=>'Debug','type'=>'debug','body'=>'No user logged in'));
}
return $status;
}
/**
* Gets the currently logged in user from the session.
* Returns FALSE if no user is currently logged in.
*
* @param boolean Check token users too
* @return mixed
*/
public function get_user($tokenuser=TRUE) {
$user = parent::get_user();
// If we are not logged in, see if there is token for the usre
if ($tokenuser AND $user === FALSE AND $token=Session::instance()->get('token')) {
$user = $this->_get_token_user($token);
}
return $user;
}
/**
* 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 mixed The user
*/
private function _get_token_user($token) {
// This has been implemented, as we sometimes we seem to come here twice
static $user = NULL;
if (! is_null($user))
return $user;
$mmto = ORM::factory('module_method_token',array('token'=>$token));
$user = FALSE;
if ($mmto->loaded()) {
if (! is_null($mmto->date_expire) AND $mmto->date_expire < time()) {
SystemMessage::add(array(
'title'=>_('Token Not Valid'),
'type'=>'warning',
'body'=>_('Token expired')));
// @todo Log the token deletion
Session::instance()->delete('token');
$mmto->delete();
} elseif (! is_null($mmto->uses) AND $mmto->uses < 1) {
SystemMessage::add(array(
'title'=>_('Token Not Valid'),
'type'=>'warning',
'body'=>_('Token expired')));
// @todo Log the token deletion
Session::instance()->delete('token');
$mmto->delete();
} else {
// Check that the token is for this URI
$mo = ORM::factory('module',array('name'=>Request::current()->controller()));
$mmo = ORM::factory('module_method',array(
'module_id'=>$mo->id,
'name'=>Request::current()->directory() ? sprintf('%s_%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action()
));
// Ignore the token if this is not the right method.
if ($mmo->id == $mmto->method_id) {
// 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);
$user = ORM::factory('account',$mmto->account_id);
$user->log(sprintf('Token %s used for method %s',$mmto->token,$mmto->method_id));
}
}
}
return $user;
}
/**
* 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($user->unique_key($username), '=', $username)->find();
}
// If the passwords match, perform a login
if ($user->status AND $user->has_any('group',ORM::factory('group',array('name'=>'Registered Users'))->list_childgrps(TRUE)) AND $user->password === $password)
{
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
// @todo figure out where this is best to go
$session_change_trigger = array('cart'=>'session_id');
if (count($session_change_trigger) AND (session_id() != $oldsess)) {
foreach ($session_change_trigger as $t => $c) {
if (Config::moduleexist($c)) {
$orm = ORM::factory($t)
->where($c,'=',$oldsess);
// @todo There must be a way that ORM can update multiple records with 1 SQL
foreach ($orm->find_all() as $o)
$o->set('session_id',session_id())
->update();
}
}
}
return TRUE;
}
// Login failed
return FALSE;
}
/**
* Determine if a user is authorised to view an account
*
* @param integer Account ID
*
* @return boolean TRUE if authorised, FALSE if not.
*/
public function authorised($aid,$afid=NULL) {
return (($ao = $this->get_user()) AND $ao->loaded() AND ($aid == $ao->id OR $ao->isAdmin() OR (! is_null($afid) AND $afid == $ao->affiliate->id))) ? TRUE : FALSE;
}
}
?>