diff options
-rw-r--r-- | README.md | 36 | ||||
-rw-r--r-- | composer.json | 5 | ||||
-rw-r--r-- | src/Jasny/Auth.php (renamed from src/Auth.php) | 84 | ||||
-rw-r--r-- | src/Jasny/Auth/User.php (renamed from src/Auth/User.php) | 14 | ||||
-rw-r--r-- | src/Jasny/Auth/byGroup.php | 81 | ||||
-rw-r--r-- | src/Jasny/Auth/byLevel.php | 74 |
6 files changed, 206 insertions, 88 deletions
@@ -9,7 +9,7 @@ Installation Install using composer - composer require jasny\auth + composer require jasny\auth Setup @@ -155,34 +155,40 @@ Check if user is allowed to do something Get a verification hash. Use it in an url and set that url in an e-mail to the user - // Create a new $user +```php +// Create a new $user - $confirmHash = generateConfirmationHash($user); - $url = 'http://' . $_SERVER['HTTP_HOST'] . '/confirm.php?hash=' . $hash; +$confirmHash = generateConfirmationHash($user); +$url = 'http://' . $_SERVER['HTTP_HOST'] . '/confirm.php?hash=' . $hash; - // send email with $url to $user +// send email with $url to $user +``` Use the confirmation hash to fetch and verify the user - // --- confirm.php +```php +// --- confirm.php - $user = Auth::fetchForConfirmation($_GET['hash']); - +$user = Auth::fetchForConfirmation($_GET['hash']); +``` ### Forgot password Forgot password works the same as the signup confirmation. - // Fetch $user by e-mail +```php +// Fetch $user by e-mail - $confirmHash = generatePasswordResetHash($user); - $url = 'http://' . $_SERVER['HTTP_HOST'] . '/reset.php?hash=' . $hash; +$confirmHash = generatePasswordResetHash($user); +$url = 'http://' . $_SERVER['HTTP_HOST'] . '/reset.php?hash=' . $hash; - // send email with $url to $user +// send email with $url to $user +``` Use the confirmation hash to fetch and verify the user - // --- reset.php +```php +// --- reset.php - $user = Auth::fetchForPasswordReset($_GET['hash']); - +$user = Auth::fetchForPasswordReset($_GET['hash']); +``` diff --git a/composer.json b/composer.json index ec9e869..89a9339 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,5 @@ { "name": "jasny/auth", - "bin": ["bin/auth"], "description": "Authentication and level based authorization", "keywords": ["auth"], "license": "MIT", @@ -20,8 +19,8 @@ "php": ">=5.4.0" }, "autoload": { - "psr-4": { - "Jasny\\": "src/" + "psr-0": { + "Jasny\\Auth": "src/" } } } diff --git a/src/Auth.php b/src/Jasny/Auth.php index f07715e..2322301 100644 --- a/src/Auth.php +++ b/src/Jasny/Auth.php @@ -5,20 +5,11 @@ namespace Jasny; use Jasny\Auth\User; /** - * Authenticate and authorize + * Authentication */ abstract class Auth { /** - * Authorization levels - * @var array - */ - protected static $levels = [ - 1 => 'user', - 1000 => 'admin' - ]; - - /** * Secret word for creating a verification hash * @var string */ @@ -49,58 +40,6 @@ abstract class Auth /** - * Get secret word - * - * @return string - */ - protected static function getSecret() - { - if (!isset(static::$secret)) throw new \Exception("Auth secret isn't set"); - return static::$secret; - } - - - /** - * Get all auth levels - * - * @return array - */ - public static function getLevels() - { - return static::$levels; - } - - /** - * Get auth level - * - * @param string $type - * @return int - */ - public static function getLevel($type) - { - $level = array_search($type, static::$levels); - if ($level === false) throw new \Exception("Authorization level '$type' isn't defined."); - - return $level; - } - - /** - * Check if user has specified auth level or more. - * - * @param int $level - * @return boolean - */ - public static function forLevel($level) - { - if ($level === 0) return true; - if (!self::user()) return false; - - if (is_string($level) && !ctype_digit($level)) $level = static::getLevel($type); - return self::user()->getAuthLevel() >= $level; - } - - - /** * Generate a password * * @param string $password @@ -123,7 +62,7 @@ abstract class Auth $user = static::fetchUserByUsername($username); if (!isset($user) || $user->getPassword() !== self::password($password, $user->getPassword())) return false; - static::setUser($user); + return static::setUser($user); } /** @@ -132,7 +71,7 @@ abstract class Auth public static function logout() { self::$user = null; - unset($_SESSION['auth_user_id']); + unset($_SESSION['auth_uid']); } @@ -147,7 +86,7 @@ abstract class Auth if (!$user->onLogin()) return false; self::$user = $user; - $_SESSION['auth_user_id'] = $user->getId(); + $_SESSION['auth_uid'] = $user->getId(); return true; } @@ -158,8 +97,8 @@ abstract class Auth */ public static function user() { - if (!isset(self::$user) && isset($_SESSION['auth_user_id'])) { - self::$user = static::fetchUserById($_SESSION['auth_user_id']); + if (!isset(self::$user) && isset($_SESSION['auth_uid'])) { + self::$user = static::fetchUserById($_SESSION['auth_uid']); } return self::$user; @@ -167,6 +106,17 @@ abstract class Auth /** + * Get secret word + * + * @return string + */ + protected static function getSecret() + { + if (!isset(static::$secret)) throw new \Exception("Auth secret isn't set"); + return static::$secret; + } + + /** * Generate a confirmation hash * * @param User $user diff --git a/src/Auth/User.php b/src/Jasny/Auth/User.php index 3606f07..8e82072 100644 --- a/src/Auth/User.php +++ b/src/Jasny/Auth/User.php @@ -29,11 +29,14 @@ interface User public function getPassword(); /** - * Get authentication level + * Get authentication level or group(s). * - * @return int + * @internal Return level (int) or level name (string) for level based auth. + * @internal Return group (string) or groups (array) for group base auth. + * + * @return int|string|array */ - public function getAuthLevel(); + public function getRole(); /** @@ -42,4 +45,9 @@ interface User * @return boolean false cancels the login */ public function onLogin(); + + /** + * Event called on logout. + */ + public function onLogout(); } diff --git a/src/Jasny/Auth/byGroup.php b/src/Jasny/Auth/byGroup.php new file mode 100644 index 0000000..2fd5c54 --- /dev/null +++ b/src/Jasny/Auth/byGroup.php @@ -0,0 +1,81 @@ +<?php + +namespace Jasny\Auth; + +/** + * Authorize by access group. + * Can be used for ACL (Access Control List). + */ +trait byGroup +{ + /** + * Authorization groups and each group is embodies. + * + * <code> + * protected static $groups = [ + * 'user' => [], + * 'developer' => ['user'], + * 'accountant' => ['user'], + * 'admin' => ['developer', 'accountant'] + * ]; + * </code> + * + * @var array + */ + protected static $groups; + + + /** + * Get all auth groups + * + * @return array + */ + public static function getGroups() + { + if (!isset(static::$groups)) { + trigger_error("Auth groups aren't set", E_USER_WARNING); + return []; + } + + return static::$groups; + } + + /** + * Get group and all groups it embodies. + * + * @return array + */ + public static function expandGroup($group) + { + $groups = [$group]; + + if (!empty(self::$groups[$group])) { + foreach (self::$groups[$group] as $sub) { + $groups = array_merge($groups, static::expandGroup($sub)); + } + + $groups = array_unique($groups); + } + + return $groups; + } + + /** + * Check if user is in specified access group. + * + * @param int $group + * @return boolean + */ + public static function authorize($group) + { + if (!self::user()) return false; + + $roles = self::user()->getRole(); + + foreach ($roles as $role) { + $roles = array_merge($roles, self::expandGroup($role)); + } + + return in_array($group, $roles); + } +} diff --git a/src/Jasny/Auth/byLevel.php b/src/Jasny/Auth/byLevel.php new file mode 100644 index 0000000..521cbae --- /dev/null +++ b/src/Jasny/Auth/byLevel.php @@ -0,0 +1,74 @@ +<?php + +namespace Jasny\Auth; + +/** + * Authorize by access level. + */ +trait byLevel +{ + /** + * Authorization levels. + * Level names should not contain only digits. + * + * <code> + * protected static $groups = [ + * 'user' => 1, + * 'moderator' => 100, + * 'admin' => 1000 + * ]; + * </code> + * + * @var array + */ + protected static $levels; + + + /** + * Get all access levels. + * + * @return array + */ + public static function getLevels() + { + if (!isset(static::$levels)) { + trigger_error("Auth levels aren't set", E_USER_WARNING); + return []; + } + + return static::$levels; + } + + /** + * Get access level + * + * @param string $name Level name + * @return int + */ + public static function getLevel($name) + { + $levels = static::getLevels(); + if (!isset($levels[$name])) throw new \Exception("Authorization level '$name' isn't defined."); + + return $levels[$name]; + } + + /** + * Check if user has specified access level or more. + * + * @param int|string $level + * @return boolean + */ + public static function authorize($level) + { + if ($level === 0) return true; + if (!static::user()) return false; + + if (is_string($level) && !ctype_digit($level)) $level = static::getLevel($level); + + $role = static::user()->getRole(); + if (is_string($role) && !ctype_digit($role)) $role = static::getLevel($role); + + return $role >= $level; + } +} |