Initial commit of Session/Authentication code
Plugin architecture with single Database-backed implementation.
This commit is contained in:
110
source/lib/SihnonFramework/Auth.class.php
Normal file
110
source/lib/SihnonFramework/Auth.class.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth {
|
||||
|
||||
protected $config;
|
||||
protected $session;
|
||||
|
||||
protected $backend;
|
||||
protected $user;
|
||||
protected $authenticated;
|
||||
|
||||
public function __construct(Sihnon_Config $config, Sihnon_Session $session) {
|
||||
$this->config = $config;
|
||||
$this->session = $session;
|
||||
$this->authenticated = false;
|
||||
|
||||
$this->init($this->config->get('auth'));
|
||||
}
|
||||
|
||||
protected function init($backend) {
|
||||
$this->backend = Sihnon_Auth_PluginFactory::create($config, $backend);
|
||||
$this->restoreSession();
|
||||
}
|
||||
|
||||
public function isAuthenticated() {
|
||||
return $this->authenticated;
|
||||
}
|
||||
|
||||
public function saveSession() {
|
||||
if ($this->user) {
|
||||
$this->session->set('user.id', $this->user->username());
|
||||
}
|
||||
}
|
||||
|
||||
public function clearSession() {
|
||||
$this->session->delete('user.id');
|
||||
}
|
||||
|
||||
public function restoreSession() {
|
||||
if ($this->session->exists('user.id')) {
|
||||
$this->user = $this->backend->authenticateSession($this->session->get('user.id'));
|
||||
$this->authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function register($username, $password) {
|
||||
$this->user = $this->addUser($username, $password);
|
||||
$this->authenticated = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPlugin methods
|
||||
*/
|
||||
|
||||
public function authenticate($username, $password) {
|
||||
$this->user = $this->backend->authenticate($username, $password);
|
||||
$this->authenticated = true;
|
||||
|
||||
$this->session->securityLeveLChanged();
|
||||
$this->saveSession();
|
||||
}
|
||||
|
||||
public function deauthenticate() {
|
||||
$this->user = null;
|
||||
$this->authenticated = false;
|
||||
|
||||
$this->clearSession();
|
||||
}
|
||||
|
||||
/*
|
||||
* IUpdateable methods
|
||||
*/
|
||||
|
||||
public function addUser($username, $password) {
|
||||
return $this->backend->addUser($username, $password);
|
||||
}
|
||||
|
||||
public function removeUser() {
|
||||
$this->backend->removeUser($this->user);
|
||||
$this->user = null;
|
||||
$this->authenticated = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPermissionable methods
|
||||
*/
|
||||
|
||||
public function isAdministrator() {
|
||||
if ( ! $this->user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->backend->isAdministrator($this->user);
|
||||
}
|
||||
|
||||
/*
|
||||
* IFinelyPermissionable methods
|
||||
*/
|
||||
|
||||
public function hasPermission($permission) {
|
||||
if ( ! $this->user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->backend->hasPermission($this->user, $permission);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
interface SihnonFramework_Auth_IFinelyPermissionable extends Sihnon_Auth_IPermissionable {
|
||||
|
||||
public function hasPermission(Sihnon_Auth_IUser $user, $permission);
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
interface SihnonFramework_Auth_IPermissionable {
|
||||
|
||||
public function isAdministrator(Sihnon_Auth_IUser $user);
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
23
source/lib/SihnonFramework/Auth/IPlugin.class.php
Normal file
23
source/lib/SihnonFramework/Auth/IPlugin.class.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
interface SihnonFramework_Auth_IPlugin extends Sihnon_IPlugin {
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Auth Plugin
|
||||
*
|
||||
* @param SihnonFramework_Config $config Config option to retrieve plugin configuration
|
||||
* @return SihnonFramework_Auth_IPlugin
|
||||
*/
|
||||
public static function create(SihnonFramework_Config $config);
|
||||
|
||||
public function userExists($username);
|
||||
|
||||
public function listUsers();
|
||||
|
||||
public function authenticate($username, $password);
|
||||
|
||||
public function authenticateSession($username);
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
13
source/lib/SihnonFramework/Auth/IUpdateable.class.php
Normal file
13
source/lib/SihnonFramework/Auth/IUpdateable.class.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
interface SihnonFramework_Auth_IUpdateable {
|
||||
|
||||
public function addUser($username, $password);
|
||||
|
||||
public function removeUser(Sihnon_Auth_IUser $user);
|
||||
|
||||
public function changePassword(Sihnon_Auth_IUser $user, $new_password);
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
11
source/lib/SihnonFramework/Auth/IUser.class.php
Normal file
11
source/lib/SihnonFramework/Auth/IUser.class.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
interface SihnonFramework_Auth_IUser {
|
||||
|
||||
public function username();
|
||||
|
||||
public function checkPassword($password);
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
83
source/lib/SihnonFramework/Auth/Plugin/Database.class.php
Normal file
83
source/lib/SihnonFramework/Auth/Plugin/Database.class.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_Plugin_Database
|
||||
extends Sihnon_PluginBase
|
||||
implements Sihnon_Auth_IPlugin,
|
||||
Sihnon_Auth_IUpdateable,
|
||||
Sihnon_Auth_IFinelyPermissionable {
|
||||
|
||||
protected $config;
|
||||
protected $database;
|
||||
|
||||
protected function __construct($config) {
|
||||
$this->config = $config;
|
||||
$this->database = SihnonFramework_Main::instance()->database();
|
||||
}
|
||||
|
||||
/*
|
||||
* IPlugin methods
|
||||
*/
|
||||
|
||||
public static function create(SihnonFramework_Config $config) {
|
||||
return new self($config);
|
||||
}
|
||||
|
||||
public function userExists($username) {
|
||||
return Sihnon_Auth_Plugin_Database_User::exists($username);
|
||||
}
|
||||
|
||||
public function listUsers() {
|
||||
return Sihnon_Auth_Plugin_Database_User::all();
|
||||
}
|
||||
|
||||
public function authenticate($username, $password) {
|
||||
$user = Sihnon_Auth_Plugin_Database_User::from('username', $username);
|
||||
|
||||
if ( ! $user->checkPassword($password)) {
|
||||
throw new Sihnon_Exception_IncorrectPassword();
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function authenticateSession($username) {
|
||||
return Sihnon_Auth_Plugin_Database_User::from('username', $username);
|
||||
}
|
||||
|
||||
/*
|
||||
* IUpdateable methods
|
||||
*/
|
||||
|
||||
public function addUser($username, $password) {
|
||||
return Sihnon_Auth_Plugin_Database_User::add($username, $password);
|
||||
}
|
||||
|
||||
public function removeUser(Sihnon_Auth_IUser $user) {
|
||||
$user->delete();
|
||||
}
|
||||
|
||||
public function changePassword(Sihnon_Auth_IUser $user, $new_password) {
|
||||
$user->changePassword($new_password);
|
||||
}
|
||||
|
||||
/*
|
||||
* IPermissionable methods
|
||||
*/
|
||||
|
||||
public function isAdministrator(Sihnon_Auth_IUser $user) {
|
||||
// As this class supports fine-grained permissions, map the isAdministrator function to the Superadmin privilege
|
||||
// to fallback for badly written applications
|
||||
return $user->hasPermission(Sihnon_Auth_Plugin_Database_Permission::PERM_Administrator);
|
||||
}
|
||||
|
||||
/*
|
||||
* IFinelyPermissionable methods
|
||||
*/
|
||||
|
||||
public function hasPermission(Sihnon_Auth_IUser $user, $permission) {
|
||||
return new $user->hasPermission($permission);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_Plugin_Database_Group extends Sihnon_DatabaseObject {
|
||||
|
||||
protected static $table = 'group';
|
||||
|
||||
protected $_db_id;
|
||||
protected $_db_name;
|
||||
protected $_db_description;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_Plugin_Database_GroupPermission extends Sihnon_DatabaseObject {
|
||||
|
||||
protected static $table = 'grouppermission';
|
||||
|
||||
protected $_db_id;
|
||||
protected $_db_group;
|
||||
protected $_db_permission;
|
||||
protected $_db_added;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_Plugin_Database_Permission extends Sihnon_DatabaseObject {
|
||||
|
||||
/*
|
||||
* Built-in permissions
|
||||
*/
|
||||
|
||||
// The Administrator permission always exists, and is always offers the most functionality
|
||||
// This maps to the isAdministrator method for coarse-grained permissions.
|
||||
const PERM_Administrator = 1;
|
||||
|
||||
protected static $table = 'permission';
|
||||
|
||||
protected $_db_id;
|
||||
protected $_db_name;
|
||||
protected $_db_description;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_Plugin_Database_User extends Sihnon_DatabaseObject implements Sihnon_Auth_IUser {
|
||||
|
||||
protected static $table = 'user';
|
||||
|
||||
protected $_db_id;
|
||||
protected $_db_username;
|
||||
protected $_db_password;
|
||||
protected $_db_fullname;
|
||||
protected $_db_email;
|
||||
protected $_db_last_login;
|
||||
protected $_db_last_password_change;
|
||||
|
||||
protected $groups = null;
|
||||
protected $permissions = null;
|
||||
|
||||
public static function exists($username) {
|
||||
return static::exists('username', $username);
|
||||
}
|
||||
|
||||
public static function add($username, $password) {
|
||||
$user = new self();
|
||||
$user->username = $username;
|
||||
$user->password = sha1($password);
|
||||
$user->last_password_change = time();
|
||||
$user->create();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function username() {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function checkPassword($password) {
|
||||
return ($this->password == sha1($password));
|
||||
}
|
||||
|
||||
public function changePassword($new_password) {
|
||||
$this->password = sha1($new_password);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function groups($ignore_cache = false) {
|
||||
if ($this->groups === null || $ignore_cache) {
|
||||
$this->groups = Sihnon_Auth_Plugin_Database_Group::all_for('user', $this->id, 'groups_by_user');
|
||||
}
|
||||
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
public function permissions($ignore_cache = false) {
|
||||
if ($this->permissions === null || $ignore_cache) {
|
||||
$this->permissions = Sihnon_Auth_Plugin_Database_Permission::all_for('user', $this->id, 'permissions_by_user');
|
||||
}
|
||||
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
public function hasPermission($permission) {
|
||||
$permissions = $this->permissions();
|
||||
foreach ($permissions as $has_permission) {
|
||||
if ($permission == $has_permission->id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_Plugin_Database_UserGroup extends Sihnon_DatabaseObject {
|
||||
|
||||
protected static $table = 'uergroup';
|
||||
|
||||
protected $_db_id;
|
||||
protected $_db_user;
|
||||
protected $_db_group;
|
||||
protected $_db_added;
|
||||
|
||||
|
||||
}
|
||||
30
source/lib/SihnonFramework/Auth/PluginFactory.class.php
Normal file
30
source/lib/SihnonFramework/Auth/PluginFactory.class.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Auth_PluginFactory extends Sihnon_PluginFactory {
|
||||
|
||||
protected static $plugin_prefix = 'Sihnon_Auth_Plugin_';
|
||||
protected static $plugin_interface = 'SihnonFramework_Auth_IPlugin';
|
||||
protected static $plugin_dir = array(
|
||||
SihnonFramework_Lib => 'SihnonFramework/Auth/Plugin/',
|
||||
Sihnon_Lib => 'Sihnon/Auth/Plugin/',
|
||||
);
|
||||
|
||||
public static function init() {
|
||||
|
||||
}
|
||||
|
||||
public static function create(SihnonFramework_Config $config, $plugin) {
|
||||
self::ensureScanned();
|
||||
|
||||
if (! self::isValidPlugin($plugin)) {
|
||||
throw new Sihnon_Exception_InvalidPluginName($plugin);
|
||||
}
|
||||
|
||||
$classname = self::classname($plugin);
|
||||
|
||||
return call_user_func(array($classname, 'create'), $config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -39,4 +39,9 @@ class SihnonFramework_Exception_LogException extends SihnonFramework_E
|
||||
class SihnonFramework_Exception_LogFileNotWriteable extends SihnonFramework_Exception_LogException {};
|
||||
class SihnonFramework_Exception_InvalidLog extends SihnonFramework_Exception_LogException {};
|
||||
|
||||
class SihnonFramework_Exception_AuthException extends SihnonFramework_Exception {};
|
||||
class SihnonFramework_Exception_UnknownUser extends SihnonFramework_Exception_AuthException {};
|
||||
class SihnonFramework_Exception_IncorrectPassword extends SihnonFramework_Exception_AuthException {};
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -17,6 +17,8 @@ class SihnonFramework_Main {
|
||||
protected $database;
|
||||
protected $log;
|
||||
protected $cache;
|
||||
protected $session;
|
||||
protected $auth;
|
||||
|
||||
protected $base_uri;
|
||||
|
||||
@@ -38,6 +40,9 @@ class SihnonFramework_Main {
|
||||
$this->log = new Sihnon_Log($this->config);
|
||||
|
||||
$this->cache = new Sihnon_Cache($this->config);
|
||||
|
||||
$this->session = new Sihnon_Session($this->config);
|
||||
$this->auth = new Sihnon_Auth($this->config, $this->session);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,6 +91,22 @@ class SihnonFramework_Main {
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SihnonFramework_Session
|
||||
*/
|
||||
public function session() {
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SihnonFramework_Auth
|
||||
*/
|
||||
public function auth() {
|
||||
return $this->auth;
|
||||
}
|
||||
|
||||
public function baseUri() {
|
||||
return $this->base_uri;
|
||||
}
|
||||
|
||||
61
source/lib/SihnonFramework/Session.class.php
Normal file
61
source/lib/SihnonFramework/Session.class.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
class SihnonFramework_Session {
|
||||
|
||||
protected $config;
|
||||
|
||||
protected $state;
|
||||
protected $dirty;
|
||||
|
||||
public function __construct(Sihnon_Config $config) {
|
||||
$this->config = $config;
|
||||
$this->dirty = false;
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
$this->teardown();
|
||||
}
|
||||
|
||||
protected function init() {
|
||||
session_start();
|
||||
$this->state = $_SESSION;
|
||||
}
|
||||
|
||||
protected function teardown() {
|
||||
if ($this->dirty) {
|
||||
$_SESSION = $this->state;
|
||||
session_write_close();
|
||||
}
|
||||
}
|
||||
|
||||
public function set($name, $value) {
|
||||
$this->state[$name] = $value;
|
||||
$this->dirty = true;
|
||||
}
|
||||
|
||||
public function get($name, $value, $default = null) {
|
||||
if ( ! $this->exists($name)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->state[$name];
|
||||
}
|
||||
|
||||
public function exists($name) {
|
||||
return isset($this->state[$name]);
|
||||
}
|
||||
|
||||
public function delete($name) {
|
||||
unset($this->state[$name]);
|
||||
$this->dirty = true;
|
||||
}
|
||||
|
||||
public function securityLeveLChanged() {
|
||||
session_regenerate_id(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user