Building in security capabilities.

This commit is contained in:
Josh Sherman 2010-10-06 00:01:49 -04:00
parent 0a6c124302
commit 9fe5ce72d4
7 changed files with 282 additions and 29 deletions

View file

@ -115,14 +115,12 @@ class Config extends Object
*
* Prohibits the direct modification of module variables.
*
* @param string $name name of the variable to be set
* @param mixed $value value of the variable to be set
* @return boolean false
* @param string $name name of the variable to be set
* @param mixed $value value of the variable to be set
*/
public function __set($name, $value)
{
trigger_error('Cannot set config variables directly', E_USER_ERROR);
return false;
throw new Exception('Cannot set config variables directly', E_USER_ERROR);
}
/**

View file

@ -40,13 +40,13 @@ class Controller extends Object
// Generate a generic "site down" message
if ($this->config->pickles['disabled'])
{
Error::fatal($_SERVER['SERVER_NAME'] . ' is currently<br />down for maintenance');
throw new Exception($_SERVER['SERVER_NAME'] . ' is currently<br />down for maintenance');
}
// Ack, not sure what page to load, throw an error
if (!isset($_REQUEST['request']) && (empty($this->config->pickles['default']) || $this->config->pickles['default'] == null))
{
Error::fatal('Unable complete this request because no URI was provided and there is no default module specified in config.ini');
throw new Exception('Unable complete this request because no URI was provided and there is no default module specified in config.ini');
}
// Loads the requested module's information
if (isset($_REQUEST['request']) && trim($_REQUEST['request']) != '')
@ -83,7 +83,7 @@ class Controller extends Object
unset($basename);
$module_exists = (isset($module_filename) && $module_filename != null && file_exists($module_filename));
$module_exists = (isset($module_filename) && $module_filename != null && file_exists($module_filename));
// Instantiates an instance of the module
if ($module_exists)
@ -120,6 +120,20 @@ class Controller extends Object
}
}
// Validates security level
if ($module->security !== false)
{
// @todo If no type is set, default to isLevel (safer)
// @todo If array is present and no type set, validate against each level there
// @todo Is array is present under type, validate against each level accordingly
if (Security::isLevel($module->security) == false)
{
// @todo Redirect to login page, potentially configured in the config, else /login
// @todo Set variable for the destination, perhaps $_SESSION['__pickles']['login']['destination']
exit;
}
}
// Validates the rendering engine
// @todo Need to validate against the module's return type(s)
$engine = $module->engine;
@ -149,7 +163,7 @@ class Controller extends Object
{
if (!isset($_REQUEST['request']))
{
Error::fatal('Way to go, you\'ve successfully created an infinite redirect loop. Good thing I was here or you would have been served with a pretty ugly browser error.<br /><br />So here\'s the deal, no templates were able to be loaded. Make sure your parent and child templates actually exist and if you\'re using non-default values, make sure they\'re defined correctly in your config.');
throw new Exception('Way to go, you\'ve successfully created an infinite redirect loop. Good thing I was here or you would have been served with a pretty ugly browser error.<br /><br />So here\'s the deal, no templates were able to be loaded. Make sure your parent and child templates actually exist and if you\'re using non-default values, make sure they\'re defined correctly in your config.');
}
else
{
@ -165,6 +179,7 @@ class Controller extends Object
}
}
$meta_data = null;
$module_return = null;
$profiler = (isset($this->config->pickles['profiler']) && $this->config->pickles['profiler'] == true);
@ -182,6 +197,13 @@ class Controller extends Object
Profiler::log($module, '__default');
}
// Sets meta data from the module
$display->setMetaData(array(
'title' => $module->title,
'description' => $module->description,
'keywords' => $module->keywords
));
/**
* Note to Self: When building in caching will need to let the
* module know to use the cache, either passing in a variable

View file

@ -63,6 +63,14 @@ abstract class Display_Common extends Object
*/
protected $js_basename = '';
/**
* Meta Data
*
* @access protected
* @var array
*/
protected $meta_data = null;
/**
* Module Return Data
*
@ -135,6 +143,18 @@ abstract class Display_Common extends Object
$this->js_basename = $js_basename;
}
/**
* Set Meta Data
*
* Sets the meta data from the module so the display class can use it
*
* @param array $meta_data key/value array of data
*/
public function setMetaData($meta_data)
{
$this->meta_data = $meta_data;
}
/**
* Set Module Return
*

View file

@ -64,6 +64,7 @@ class Display_PHP extends Display_Common
$form_class = (isset($this->config->pickles['form']) ? $this->config->pickles['form'] : 'Form');
$__config = $this->config;
$__meta = $this->meta_data;
$__module = $this->module_return;
$__css_class = $this->css_class;
$__js_file = $this->js_basename;

View file

@ -28,7 +28,7 @@
class Module extends Object
{
/**
* Database
* Database object
*
* @access protected
* @var object
@ -59,14 +59,6 @@ class Module extends Object
*/
protected $keywords = null;
/**
* Access level of the page
*
* @access protected
* @var boolean, null by default
*/
protected $access = null;
/**
* Secure
*
@ -78,6 +70,14 @@ class Module extends Object
*/
protected $secure = null;
/**
* Security settings of the page
*
* @access protected
* @var boolean, null by default
*/
protected $security = null;
/**
* Session
*
@ -133,6 +133,7 @@ class Module extends Object
* @access protected
* @var array, null by default
* @todo Currently the super globals are not being cleared out
* @todo Not even sure I want to implement this at this point
*/
protected $request = null;
@ -177,14 +178,12 @@ class Module extends Object
*
* Prohibits the direct modification of module variables.
*
* @param string $name name of the variable to be set
* @param mixed $value value of the variable to be set
* @return boolean false
* @param string $name name of the variable to be set
* @param mixed $value value of the variable to be set
*/
public function __set($name, $value)
{
trigger_error('Cannot set module variables directly', E_USER_ERROR);
return false;
throw new Exception('Cannot set module variables directly');
}
/**
@ -230,8 +229,7 @@ class Module extends Object
}
else
{
trigger_error('Only Controller can perform setRequest()', E_USER_ERROR);
return false;
throw new Exception('Only Controller can perform setRequest()');
}
}
}

183
classes/Security.php Normal file
View file

@ -0,0 +1,183 @@
<?php
/**
* Security System for PICKLES
*
* PHP version 5
*
* Licensed under the GNU General Public License Version 3
* Redistribution of these files must retain the above copyright notice.
*
* @package PICKLES
* @author Josh Sherman <josh@phpwithpickles.org>
* @copyright Copyright 2007-2010, Gravity Boulevard, LLC
* @license http://www.gnu.org/licenses/gpl.html GPL v3
* @link http://phpwithpickles.org
*/
/**
* Security Class
*
* Collection of static methods for handling security within a website running
* on PICKLES. Requires sessions to be enabled.
*
* @usage <code>Security::setLevel('level');</code>
* @usage <code>Security::isLevel('level');</code>
*/
class Security
{
/**
* Check Session
*
* Checks if sessions are enabled.
*
* @return boolean whether or not sessions are enabled
*/
private static function checkSession()
{
if (session_id() == '')
{
throw new Exception('Sessions must be enabled to use Security class');
}
else
{
return true;
}
}
/**
* Check Level
*
* Checks if a passed level is an integer and/or properly defined in the
* site's configuration file.
*
* @param mixed access level to validate
* @return whether ot not the access level is valid
*/
private static function checkLevel(&$access_level)
{
if (is_int($access_level))
{
return true;
}
else
{
$config = Config::getInstance();
// Attempts to validate the string passed
if (isset($config->security[$access_level]))
{
if (is_numeric($config->security[$access_level]))
{
$access_level = (int)$config->security[$access_level];
return true;
}
else
{
throw new Exception('Level "' . $access_level . '" is not numeric in config.ini');
}
}
else
{
throw new Exception('Level "' . $access_level . '" is not defined in config.ini');
}
}
}
/**
* Set Level
*
* Sets the security level.
*
* @param mixed $access_level access level to set this session to
* @return boolean true on success, thrown exception on error
*/
public static function setLevel($access_level)
{
if (self::checkSession() && self::checkLevel($access_level))
{
$_SESSION['__pickles']['security']['level'] = $access_level;
}
return true;
}
/**
* Clear Level
*
* Clears out the security level.
*
* @return boolean true
*/
public static function clearLevel()
{
if (isset($_SESSION['__pickles']['security']['level']))
{
$_SESSION['__pickles']['security']['level'] = null;
}
return true;
}
/**
* Is Level
*
* Checks the user's access level is exactly the passed level
*
* @param mixed $access_level access level to be checked against
* @param mixed $user_level optional user's access level
* @return boolean whether or not the user is that level
*/
public static function isLevel($access_level, $user_level = null)
{
if (self::checkSession() && self::checkLevel($access_level) && ($user_level == null || ($user_level != null && self::checkLevel($user_level))))
{
if ($user_level != null)
{
return ($user_level == $access_level);
}
elseif (isset($_SESSION['__pickles']['security']['level']))
{
return ($_SESSION['__pickles']['security']['level'] == $access_level);
}
else
{
throw new Exception('Security level has not been set');
}
}
return false;
}
/**
* Has Level
*
* Checks the user's access level against the passed level.
*
* @param integer $access_level access level to be checked against
* @param integer $user_level optional user's access level
* @return boolean whether or not the user has access
*/
public static function hasLevel($access_level, $user_level = null)
{
if (self::checkSession() && self::checkLevel($access_level) && ($user_level == null || ($user_level != null && self::checkLevel($user_level))))
{
if ($user_level != null)
{
return ($user_level >= $access_level);
}
elseif (isset($_SESSION['__pickles']['security']['level']))
{
return ($_SESSION['__pickles']['security']['level'] >= $access_level);
}
else
{
throw new Exception('Security level has not been set');
}
}
return false;
}
}
?>

View file

@ -53,13 +53,16 @@ define('JSON_AVAILABLE', function_exists('json_encode'));
// }}}
// {{{ Defaults some important configuration options
// Error reporting is not modified initially
// Feel free to uncomment these lines if you want error reporting on before the config is loaded
ini_set('display_errors', true);
error_reporting(-1);
// ini_set('display_errors', true);
// error_reporting(-1);
// Sets the error handler
// Sets the error and exceptios handlers
set_error_handler('__handleError');
set_exception_handler('__handleException');
// Defaults timezone to UTC if not set
if (ini_get('date.timezone') == '')
@ -67,6 +70,10 @@ if (ini_get('date.timezone') == '')
ini_set('date.timezone', 'Etc/UTC');
}
// }}}
// {{{ Loads the configuration file(1)
// Loads the base config
$config = Config::getInstance();
@ -91,6 +98,10 @@ if ($config->environment != false && is_array($config->environment))
}
}
// }}}
// {{{ Sets any configurable options
// Configures any available PHP configuration options
if (isset($config->php['display_error']))
{
@ -102,7 +113,7 @@ if (isset($config->php['error_reporting']))
error_reporting($config->php['error_reporting']);
}
// Sets the timezone to avoid warnings
// Sets the timezone
if (isset($config->php['date.timezone']))
{
ini_set('date.timezone', $config->php['date.timezone']);
@ -114,6 +125,14 @@ if (isset($config->php['error_handler']))
set_error_handler($config->php['error_handler']);
}
// Sets the exception handler
if (isset($config->php['exception_handler']))
{
set_exception_handler($config->php['exception_handler']);
}
// }}}
/**
* Magic function to automatically load classes
*
@ -170,4 +189,16 @@ function __handleError($number, $string, $file, $line, array $context)
throw new ErrorException($string, 0, $number, $file, $line);
}
/**
* Exception handling function
*
* Catches thrown exceptions and displays them.
*
* @param object $exception the exception
*/
function __handleException($exception)
{
Error::fatal($exception->getMessage());
}
?>