diff --git a/source/lib/SihnonFramework/Auth.class.php b/source/lib/SihnonFramework/Auth.class.php new file mode 100644 index 0000000..38b71ed --- /dev/null +++ b/source/lib/SihnonFramework/Auth.class.php @@ -0,0 +1,110 @@ +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); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php b/source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php new file mode 100644 index 0000000..3f291c0 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IPermissionable.class.php b/source/lib/SihnonFramework/Auth/IPermissionable.class.php new file mode 100644 index 0000000..75abc3c --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IPermissionable.class.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IPlugin.class.php b/source/lib/SihnonFramework/Auth/IPlugin.class.php new file mode 100644 index 0000000..26dd425 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IPlugin.class.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IUpdateable.class.php b/source/lib/SihnonFramework/Auth/IUpdateable.class.php new file mode 100644 index 0000000..971c956 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IUpdateable.class.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IUser.class.php b/source/lib/SihnonFramework/Auth/IUser.class.php new file mode 100644 index 0000000..5ed5814 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IUser.class.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php new file mode 100644 index 0000000..5bdad0f --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php @@ -0,0 +1,83 @@ +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); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php new file mode 100644 index 0000000..b707c40 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php @@ -0,0 +1,12 @@ +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; + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php new file mode 100644 index 0000000..83ef191 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php @@ -0,0 +1,13 @@ + '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); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index d17205d..5ec39c6 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -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 {}; + + ?> diff --git a/source/lib/SihnonFramework/Main.class.php b/source/lib/SihnonFramework/Main.class.php index 754dbda..ba0062e 100644 --- a/source/lib/SihnonFramework/Main.class.php +++ b/source/lib/SihnonFramework/Main.class.php @@ -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; } diff --git a/source/lib/SihnonFramework/Session.class.php b/source/lib/SihnonFramework/Session.class.php new file mode 100644 index 0000000..c179b6f --- /dev/null +++ b/source/lib/SihnonFramework/Session.class.php @@ -0,0 +1,61 @@ +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); + } + +} + +?> \ No newline at end of file